Patch #34204: [Render Animation] Fails with "Error: Specified sample_fmt is not suppo...
[blender.git] / source / blender / blenkernel / intern / library.c
index 1c13c96..4038dd2 100644 (file)
@@ -47,6 +47,7 @@
 #include "DNA_brush_types.h"
 #include "DNA_camera_types.h"
 #include "DNA_group_types.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_ipo_types.h"
 #include "DNA_key_types.h"
 #include "DNA_lamp_types.h"
@@ -54,6 +55,8 @@
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_nla_types.h"
 #include "DNA_node_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_vfont_types.h"
 #include "DNA_windowmanager_types.h"
 #include "DNA_world_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_movieclip_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_dynstr.h"
 #include "BLI_utildefines.h"
-#include "BLI_bpath.h"
+#include "BKE_bpath.h"
 
+#include "BKE_action.h"
 #include "BKE_animsys.h"
+#include "BKE_armature.h"
+#include "BKE_brush.h"
 #include "BKE_camera.h"
 #include "BKE_context.h"
-#include "BKE_lamp.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_global.h"
-#include "BKE_sound.h"
-#include "BKE_object.h"
-#include "BKE_screen.h"
-#include "BKE_mesh.h"
-#include "BKE_material.h"
 #include "BKE_curve.h"
-#include "BKE_mball.h"
-#include "BKE_text.h"
-#include "BKE_texture.h"
-#include "BKE_scene.h"
+#include "BKE_fcurve.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_gpencil.h"
+#include "BKE_idprop.h"
 #include "BKE_icons.h"
 #include "BKE_image.h"
 #include "BKE_ipo.h"
 #include "BKE_key.h"
-#include "BKE_world.h"
-#include "BKE_font.h"
-#include "BKE_group.h"
+#include "BKE_lamp.h"
 #include "BKE_lattice.h"
-#include "BKE_armature.h"
-#include "BKE_action.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_movieclip.h"
+#include "BKE_mask.h"
 #include "BKE_node.h"
-#include "BKE_brush.h"
-#include "BKE_idprop.h"
+#include "BKE_object.h"
 #include "BKE_particle.h"
-#include "BKE_gpencil.h"
-#include "BKE_fcurve.h"
+#include "BKE_packedFile.h"
 #include "BKE_speaker.h"
-#include "BKE_utildefines.h"
-#include "BKE_movieclip.h"
+#include "BKE_sound.h"
+#include "BKE_screen.h"
+#include "BKE_scene.h"
+#include "BKE_text.h"
+#include "BKE_texture.h"
+#include "BKE_world.h"
 
 #include "RNA_access.h"
 
 #include "BPY_extern.h"
 #endif
 
-#define MAX_IDPUP              60      /* was 24 */
+#define MAX_IDPUP  60  /* was 24 */
 
 /* GS reads the memory pointed at in a specific ordering. 
  * only use this definition, makes little and big endian systems
  * work fine, in conjunction with MAKE_ID */
 
-/* from blendef: */
-#define GS(a)  (*((short *)(a)))
-
 /* ************* general ************************ */
 
 
  * also note that the id _must_ have a library - campbell */
 void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
 {
-       char *bpath_user_data[2]= {bmain->name, lib->filepath};
+       char *bpath_user_data[2] = {bmain->name, lib->filepath};
 
-       BLI_bpath_traverse_id(bmain, id,
-                                         BLI_bpath_relocate_visitor,
-                                         BLI_BPATH_TRAVERSE_SKIP_MULTIFILE,
-                                         bpath_user_data);
+       BKE_bpath_traverse_id(bmain, id,
+                             BKE_bpath_relocate_visitor,
+                             BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
+                             bpath_user_data);
 }
 
 void id_lib_extern(ID *id)
@@ -151,6 +150,16 @@ void id_lib_extern(ID *id)
        }
 }
 
+/* ensure we have a real user */
+void id_us_ensure_real(ID *id)
+{
+       if (id) {
+               if (ID_REAL_USERS(id) <= 0) {
+                       id->us = MAX2(id->us, 0) + 1;
+               }
+       }
+}
+
 void id_us_plus(ID *id)
 {
        if (id) {
@@ -162,11 +171,12 @@ void id_us_plus(ID *id)
        }
 }
 
+/* decrements the user count for *id. */
 void id_us_min(ID *id)
 {
        if (id) {
                if (id->us < 2 && (id->flag & LIB_FAKEUSER)) {
-                       id->us= 1;
+                       id->us = 1;
                }
                else if (id->us <= 0) {
                        printf("ID user decrement error: %s\n", id->name);
@@ -177,225 +187,234 @@ void id_us_min(ID *id)
        }
 }
 
-int id_make_local(ID *id, int test)
+/* calls the appropriate make_local method for the block, unless test. Returns true
+ * if the block can be made local. */
+bool id_make_local(ID *id, bool test)
 {
        if (id->flag & LIB_INDIRECT)
-               return 0;
+               return false;
 
        switch (GS(id->name)) {
                case ID_SCE:
-                       return 0; /* not implemented */
+                       return false; /* not implemented */
                case ID_LI:
-                       return 0; /* can't be linked */
+                       return false; /* can't be linked */
                case ID_OB:
                        if (!test) BKE_object_make_local((Object *)id);
-                       return 1;
+                       return true;
                case ID_ME:
                        if (!test) {
                                BKE_mesh_make_local((Mesh *)id);
                                BKE_key_make_local(((Mesh *)id)->key);
                        }
-                       return 1;
+                       return true;
                case ID_CU:
                        if (!test) {
                                BKE_curve_make_local((Curve *)id);
                                BKE_key_make_local(((Curve *)id)->key);
                        }
-                       return 1;
+                       return true;
                case ID_MB:
-                       if (!test) BKE_metaball_make_local((MetaBall *)id);
-                       return 1;
+                       if (!test) BKE_mball_make_local((MetaBall *)id);
+                       return true;
                case ID_MA:
-                       if (!test) make_local_material((Material *)id);
-                       return 1;
+                       if (!test) BKE_material_make_local((Material *)id);
+                       return true;
                case ID_TE:
-                       if (!test) make_local_texture((Tex *)id);
-                       return 1;
+                       if (!test) BKE_texture_make_local((Tex *)id);
+                       return true;
                case ID_IM:
-                       if (!test) make_local_image((Image *)id);
-                       return 1;
+                       if (!test) BKE_image_make_local((Image *)id);
+                       return true;
                case ID_LT:
                        if (!test) {
                                BKE_lattice_make_local((Lattice *)id);
                                BKE_key_make_local(((Lattice *)id)->key);
                        }
-                       return 1;
+                       return true;
                case ID_LA:
-                       if (!test) make_local_lamp((Lamp *)id);
-                       return 1;
+                       if (!test) BKE_lamp_make_local((Lamp *)id);
+                       return true;
                case ID_CA:
                        if (!test) BKE_camera_make_local((Camera *)id);
-                       return 1;
+                       return true;
                case ID_SPK:
-                       if (!test) make_local_speaker((Speaker *)id);
-                       return 1;
+                       if (!test) BKE_speaker_make_local((Speaker *)id);
+                       return true;
                case ID_IP:
-                       return 0; /* deprecated */
+                       return false; /* deprecated */
                case ID_KE:
                        if (!test) BKE_key_make_local((Key *)id);
-                       return 1;
+                       return true;
                case ID_WO:
                        if (!test) BKE_world_make_local((World *)id);
-                       return 1;
+                       return true;
                case ID_SCR:
-                       return 0; /* can't be linked */
+                       return false; /* can't be linked */
                case ID_VF:
-                       return 0; /* not implemented */
+                       return false; /* not implemented */
                case ID_TXT:
-                       return 0; /* not implemented */
+                       return false; /* not implemented */
                case ID_SCRIPT:
-                       return 0; /* deprecated */
+                       return false; /* deprecated */
                case ID_SO:
-                       return 0; /* not implemented */
+                       return false; /* not implemented */
                case ID_GR:
-                       return 0; /* not implemented */
+                       return false; /* not implemented */
                case ID_AR:
                        if (!test) BKE_armature_make_local((bArmature *)id);
-                       return 1;
+                       return true;
                case ID_AC:
                        if (!test) BKE_action_make_local((bAction *)id);
-                       return 1;
+                       return true;
                case ID_NT:
-                       return 0; /* not implemented */
+                       return false; /* not implemented */
                case ID_BR:
                        if (!test) BKE_brush_make_local((Brush *)id);
-                       return 1;
+                       return true;
                case ID_PA:
                        if (!test) BKE_particlesettings_make_local((ParticleSettings *)id);
-                       return 1;
+                       return true;
                case ID_WM:
-                       return 0; /* can't be linked */
+                       return false; /* can't be linked */
                case ID_GD:
-                       return 0; /* not implemented */
+                       return false; /* not implemented */
        }
 
-       return 0;
+       return false;
 }
 
-int id_copy(ID *id, ID **newid, int test)
+/**
+ * Invokes the appropriate copy method for the block and returns the result in
+ * newid, unless test. Returns true iff the block can be copied.
+ */
+bool id_copy(ID *id, ID **newid, bool test)
 {
-       if (!test) *newid= NULL;
+       if (!test) *newid = NULL;
 
        /* conventions:
         * - make shallow copy, only this ID block
         * - id.us of the new ID is set to 1 */
        switch (GS(id->name)) {
                case ID_SCE:
-                       return 0; /* can't be copied from here */
+                       return false;  /* can't be copied from here */
                case ID_LI:
-                       return 0; /* can't be copied from here */
+                       return false;  /* can't be copied from here */
                case ID_OB:
-                       if (!test) *newid = (ID *)BKE_object_copy((Object*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_object_copy((Object *)id);
+                       return true;
                case ID_ME:
-                       if (!test) *newid = (ID *)BKE_mesh_copy((Mesh*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_mesh_copy((Mesh *)id);
+                       return true;
                case ID_CU:
-                       if (!test) *newid = (ID *)BKE_curve_copy((Curve*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_curve_copy((Curve *)id);
+                       return true;
                case ID_MB:
-                       if (!test) *newid = (ID *)BKE_metaball_copy((MetaBall*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_mball_copy((MetaBall *)id);
+                       return true;
                case ID_MA:
-                       if (!test) *newid = (ID *)BKE_material_copy((Material*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_material_copy((Material *)id);
+                       return true;
                case ID_TE:
-                       if (!test) *newid = (ID *)BKE_texture_copy((Tex*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_texture_copy((Tex *)id);
+                       return true;
                case ID_IM:
-                       if (!test) *newid = (ID *)BKE_image_copy((Image*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_image_copy(G.main, (Image *)id);
+                       return true;
                case ID_LT:
-                       if (!test) *newid = (ID *)BKE_lattice_copy((Lattice*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_lattice_copy((Lattice *)id);
+                       return true;
                case ID_LA:
-                       if (!test) *newid = (ID *)BKE_lamp_copy((Lamp*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_lamp_copy((Lamp *)id);
+                       return true;
                case ID_SPK:
-                       if (!test) *newid = (ID *)BKE_speaker_copy((Speaker*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_speaker_copy((Speaker *)id);
+                       return true;
                case ID_CA:
-                       if (!test) *newid = (ID *)BKE_camera_copy((Camera*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_camera_copy((Camera *)id);
+                       return true;
                case ID_IP:
-                       return 0; /* deprecated */
+                       return false;  /* deprecated */
                case ID_KE:
-                       if (!test) *newid = (ID *)BKE_key_copy((Key*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_key_copy((Key *)id);
+                       return true;
                case ID_WO:
-                       if (!test) *newid = (ID *)BKE_world_copy((World*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_world_copy((World *)id);
+                       return true;
                case ID_SCR:
-                       return 0; /* can't be copied from here */
+                       return false;  /* can't be copied from here */
                case ID_VF:
-                       return 0; /* not implemented */
+                       return false;  /* not implemented */
                case ID_TXT:
-                       if (!test) *newid = (ID *)BKE_text_copy((Text*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_text_copy((Text *)id);
+                       return true;
                case ID_SCRIPT:
-                       return 0; /* deprecated */
+                       return false;  /* deprecated */
                case ID_SO:
-                       return 0; /* not implemented */
+                       return false;  /* not implemented */
                case ID_GR:
-                       if (!test) *newid = (ID *)BKE_group_copy((Group*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_group_copy((Group *)id);
+                       return true;
                case ID_AR:
-                       if (!test) *newid = (ID *)BKE_armature_copy((bArmature*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_armature_copy((bArmature *)id);
+                       return true;
                case ID_AC:
-                       if (!test) *newid = (ID *)BKE_action_copy((bAction*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_action_copy((bAction *)id);
+                       return true;
                case ID_NT:
-                       if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree *)id);
+                       return true;
                case ID_BR:
-                       if (!test) *newid = (ID *)BKE_brush_copy((Brush*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id);
+                       return true;
                case ID_PA:
-                       if (!test) *newid = (ID *)BKE_particlesettings_copy((ParticleSettings*)id);
-                       return 1;
+                       if (!test) *newid = (ID *)BKE_particlesettings_copy((ParticleSettings *)id);
+                       return true;
                case ID_WM:
-                       return 0; /* can't be copied from here */
+                       return false;  /* can't be copied from here */
                case ID_GD:
-                       return 0; /* not implemented */
+                       return false;  /* not implemented */
+               case ID_MSK:
+                       if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
+                       return true;
        }
        
-       return 0;
+       return false;
 }
 
-int id_unlink(ID *id, int test)
+bool id_unlink(ID *id, int test)
 {
-       Main *mainlib= G.main;
+       Main *mainlib = G.main;
        ListBase *lb;
 
        switch (GS(id->name)) {
                case ID_TXT:
-                       if (test) return 1;
+                       if (test) return true;
                        BKE_text_unlink(mainlib, (Text *)id);
                        break;
                case ID_GR:
-                       if (test) return 1;
+                       if (test) return true;
                        BKE_group_unlink((Group *)id);
                        break;
                case ID_OB:
-                       if (test) return 1;
+                       if (test) return true;
                        BKE_object_unlink((Object *)id);
                        break;
        }
 
        if (id->us == 0) {
-               if (test) return 1;
+               if (test) return true;
 
-               lb= which_libbase(mainlib, GS(id->name));
+               lb = which_libbase(mainlib, GS(id->name));
                BKE_libblock_free(lb, id);
 
-               return 1;
+               return true;
        }
 
-       return 0;
+       return false;
 }
 
-int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
+bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
 {
        ID *newid = NULL;
        PointerRNA idptr;
@@ -403,7 +422,7 @@ int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
        if (id) {
                /* if property isn't editable, we're going to have an extra block hanging around until we save */
                if (RNA_property_editable(ptr, prop)) {
-                       if (id_copy(id, &newid, 0) && newid) {
+                       if (id_copy(id, &newid, false) && newid) {
                                /* copy animation actions too */
                                BKE_copy_animdata_id_action(id);
                                /* us is 1 by convention, but RNA_property_pointer_set
@@ -415,17 +434,17 @@ int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
                                RNA_property_pointer_set(ptr, prop, idptr);
                                RNA_property_update(C, ptr, prop);
                                
-                               return 1;
+                               return true;
                        }
                }
        }
        
-       return 0;
+       return false;
 }
 
 ListBase *which_libbase(Main *mainlib, short type)
 {
-       switch ( type ) {
+       switch (type) {
                case ID_SCE:
                        return &(mainlib->scene);
                case ID_LI:
@@ -486,6 +505,8 @@ ListBase *which_libbase(Main *mainlib, short type)
                        return &(mainlib->gpencil);
                case ID_MC:
                        return &(mainlib->movieclip);
+               case ID_MSK:
+                       return &(mainlib->mask);
        }
        return NULL;
 }
@@ -495,11 +516,11 @@ void flag_listbase_ids(ListBase *lb, short flag, short value)
 {
        ID *id;
        if (value) {
-               for (id= lb->first; id; id= id->next) id->flag |= flag;
+               for (id = lb->first; id; id = id->next) id->flag |= flag;
        }
        else {
                flag = ~flag;
-               for (id= lb->first; id; id= id->next) id->flag &= flag;
+               for (id = lb->first; id; id = id->next) id->flag &= flag;
        }
 }
 
@@ -508,8 +529,8 @@ void flag_all_listbases_ids(short flag, short value)
 {
        ListBase *lbarray[MAX_LIBARRAY];
        int a;
-       a= set_listbasepointers(G.main, lbarray);
-       while (a--)     flag_listbase_ids(lbarray[a], flag, value);
+       a = set_listbasepointers(G.main, lbarray);
+       while (a--) flag_listbase_ids(lbarray[a], flag, value);
 }
 
 void recalc_all_library_objects(Main *main)
@@ -517,12 +538,18 @@ void recalc_all_library_objects(Main *main)
        Object *ob;
 
        /* flag for full recalc */
-       for (ob=main->object.first; ob; ob=ob->id.next)
+       for (ob = main->object.first; ob; ob = ob->id.next)
                if (ob->id.lib)
-                       ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
+                       ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
 }
 
-/* note: MAX_LIBARRAY define should match this code */
+/**
+ * puts into array *lb pointers to all the ListBase structs in main,
+ * and returns the number of them as the function result. This is useful for
+ * generic traversal of all the blocks in a Main (by traversing all the
+ * lists in turn), without worrying about block types.
+ *
+ * \note MAX_LIBARRAY define should match this code */
 int set_listbasepointers(Main *main, ListBase **lb)
 {
        int a = 0;
@@ -530,47 +557,48 @@ int set_listbasepointers(Main *main, ListBase **lb)
        /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last.
         * This is important because freeing data decreases usercounts of other datablocks,
         * if this data is its self freed it can crash. */
-       lb[a++]= &(main->ipo);
-       lb[a++]= &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith)
-       lb[a++]= &(main->key);
-       lb[a++]= &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */
-       lb[a++]= &(main->nodetree);
-       lb[a++]= &(main->image);
-       lb[a++]= &(main->tex);
-       lb[a++]= &(main->mat);
-       lb[a++]= &(main->vfont);
+       lb[a++] = &(main->ipo);
+       lb[a++] = &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith)
+       lb[a++] = &(main->key);
+       lb[a++] = &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */
+       lb[a++] = &(main->nodetree);
+       lb[a++] = &(main->image);
+       lb[a++] = &(main->tex);
+       lb[a++] = &(main->mat);
+       lb[a++] = &(main->vfont);
        
        /* Important!: When adding a new object type,
         * the specific data should be inserted here 
         */
 
-       lb[a++]= &(main->armature);
-
-       lb[a++]= &(main->mesh);
-       lb[a++]= &(main->curve);
-       lb[a++]= &(main->mball);
-
-       lb[a++]= &(main->latt);
-       lb[a++]= &(main->lamp);
-       lb[a++]= &(main->camera);
-
-       lb[a++]= &(main->text);
-       lb[a++]= &(main->sound);
-       lb[a++]= &(main->group);
-       lb[a++]= &(main->brush);
-       lb[a++]= &(main->script);
-       lb[a++]= &(main->particle);
-       lb[a++]= &(main->speaker);
-
-       lb[a++]= &(main->world);
-       lb[a++]= &(main->screen);
-       lb[a++]= &(main->object);
-       lb[a++]= &(main->scene);
-       lb[a++]= &(main->library);
-       lb[a++]= &(main->wm);
-       lb[a++]= &(main->movieclip);
+       lb[a++] = &(main->armature);
+
+       lb[a++] = &(main->mesh);
+       lb[a++] = &(main->curve);
+       lb[a++] = &(main->mball);
+
+       lb[a++] = &(main->latt);
+       lb[a++] = &(main->lamp);
+       lb[a++] = &(main->camera);
+
+       lb[a++] = &(main->text);
+       lb[a++] = &(main->sound);
+       lb[a++] = &(main->group);
+       lb[a++] = &(main->brush);
+       lb[a++] = &(main->script);
+       lb[a++] = &(main->particle);
+       lb[a++] = &(main->speaker);
+
+       lb[a++] = &(main->world);
+       lb[a++] = &(main->screen);
+       lb[a++] = &(main->object);
+       lb[a++] = &(main->scene);
+       lb[a++] = &(main->library);
+       lb[a++] = &(main->wm);
+       lb[a++] = &(main->movieclip);
+       lb[a++] = &(main->mask);
        
-       lb[a]= NULL;
+       lb[a] = NULL;
 
        return a;
 }
@@ -585,76 +613,80 @@ int set_listbasepointers(Main *main, ListBase **lb)
  *
  * **************************** */
 
+/**
+ * Allocates and returns memory of the right size for the specified block type,
+ * initialized to zero.
+ */
 static ID *alloc_libblock_notest(short type)
 {
-       ID *id= NULL;
+       ID *id = NULL;
        
-       switch ( type ) {
+       switch (type) {
                case ID_SCE:
-                       id= MEM_callocN(sizeof(Scene), "scene");
+                       id = MEM_callocN(sizeof(Scene), "scene");
                        break;
                case ID_LI:
-                       id= MEM_callocN(sizeof(Library), "library");
+                       id = MEM_callocN(sizeof(Library), "library");
                        break;
                case ID_OB:
-                       id= MEM_callocN(sizeof(Object), "object");
+                       id = MEM_callocN(sizeof(Object), "object");
                        break;
                case ID_ME:
-                       id= MEM_callocN(sizeof(Mesh), "mesh");
+                       id = MEM_callocN(sizeof(Mesh), "mesh");
                        break;
                case ID_CU:
-                       id= MEM_callocN(sizeof(Curve), "curve");
+                       id = MEM_callocN(sizeof(Curve), "curve");
                        break;
                case ID_MB:
-                       id= MEM_callocN(sizeof(MetaBall), "mball");
+                       id = MEM_callocN(sizeof(MetaBall), "mball");
                        break;
                case ID_MA:
-                       id= MEM_callocN(sizeof(Material), "mat");
+                       id = MEM_callocN(sizeof(Material), "mat");
                        break;
                case ID_TE:
-                       id= MEM_callocN(sizeof(Tex), "tex");
+                       id = MEM_callocN(sizeof(Tex), "tex");
                        break;
                case ID_IM:
-                       id= MEM_callocN(sizeof(Image), "image");
+                       id = MEM_callocN(sizeof(Image), "image");
                        break;
                case ID_LT:
-                       id= MEM_callocN(sizeof(Lattice), "latt");
+                       id = MEM_callocN(sizeof(Lattice), "latt");
                        break;
                case ID_LA:
-                       id= MEM_callocN(sizeof(Lamp), "lamp");
+                       id = MEM_callocN(sizeof(Lamp), "lamp");
                        break;
                case ID_CA:
-                       id= MEM_callocN(sizeof(Camera), "camera");
+                       id = MEM_callocN(sizeof(Camera), "camera");
                        break;
                case ID_IP:
-                       id= MEM_callocN(sizeof(Ipo), "ipo");
+                       id = MEM_callocN(sizeof(Ipo), "ipo");
                        break;
                case ID_KE:
-                       id= MEM_callocN(sizeof(Key), "key");
+                       id = MEM_callocN(sizeof(Key), "key");
                        break;
                case ID_WO:
-                       id= MEM_callocN(sizeof(World), "world");
+                       id = MEM_callocN(sizeof(World), "world");
                        break;
                case ID_SCR:
-                       id= MEM_callocN(sizeof(bScreen), "screen");
+                       id = MEM_callocN(sizeof(bScreen), "screen");
                        break;
                case ID_VF:
-                       id= MEM_callocN(sizeof(VFont), "vfont");
+                       id = MEM_callocN(sizeof(VFont), "vfont");
                        break;
                case ID_TXT:
-                       id= MEM_callocN(sizeof(Text), "text");
+                       id = MEM_callocN(sizeof(Text), "text");
                        break;
                case ID_SCRIPT:
-                       //XXX id= MEM_callocN(sizeof(Script), "script");
+                       //XXX id = MEM_callocN(sizeof(Script), "script");
                        break;
                case ID_SPK:
-                       id= MEM_callocN(sizeof(Speaker), "speaker");
+                       id = MEM_callocN(sizeof(Speaker), "speaker");
                        break;
                case ID_SO:
-                       id= MEM_callocN(sizeof(bSound), "sound");
+                       id = MEM_callocN(sizeof(bSound), "sound");
                        break;
                case ID_GR:
-                       id= MEM_callocN(sizeof(Group), "group");
+                       id = MEM_callocN(sizeof(Group), "group");
                        break;
                case ID_AR:
                        id = MEM_callocN(sizeof(bArmature), "armature");
@@ -680,41 +712,49 @@ static ID *alloc_libblock_notest(short type)
                case ID_MC:
                        id = MEM_callocN(sizeof(MovieClip), "Movie Clip");
                        break;
+               case ID_MSK:
+                       id = MEM_callocN(sizeof(Mask), "Mask");
+                       break;
        }
        return id;
 }
 
-/* used everywhere in blenkernel and text.c */
+/**
+ * Allocates and returns a block of the specified type, with the specified name
+ * (adjusted as necessary to ensure uniqueness), and appended to the specified list.
+ * The user count is set to 1, all other content (apart from name and links) being
+ * initialized to zero.
+ */
 void *BKE_libblock_alloc(ListBase *lb, short type, const char *name)
 {
-       ID *id= NULL;
+       ID *id = NULL;
        
-       id= alloc_libblock_notest(type);
+       id = alloc_libblock_notest(type);
        if (id) {
                BLI_addtail(lb, id);
-               id->us= 1;
+               id->us = 1;
                id->icon_id = 0;
-               *( (short *)id->name )= type;
+               *( (short *)id->name= type;
                new_id(lb, id, name);
-               /* alphabetic insterion: is in new_id */
+               /* alphabetic insertion: is in new_id */
        }
        return id;
 }
 
 /* by spec, animdata is first item after ID */
 /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */
-static void id_copy_animdata(ID *id, const short do_action)
+static void id_copy_animdata(ID *id, const bool do_action)
 {
-       AnimData *adt= BKE_animdata_from_id(id);
+       AnimData *adt = BKE_animdata_from_id(id);
        
        if (adt) {
                IdAdtTemplate *iat = (IdAdtTemplate *)id;
-               iat->adt= BKE_copy_animdata(iat->adt, do_action); /* could be set to FALSE, need to investigate */
+               iat->adt = BKE_copy_animdata(iat->adt, do_action); /* could be set to false, need to investigate */
        }
 }
 
 /* material nodes use this since they are not treated as libdata */
-void BKE_libblock_copy_data(ID *id, const ID *id_from, const short do_action)
+void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action)
 {
        if (id_from->properties)
                id->properties = IDP_CopyProperty(id_from->properties);
@@ -724,43 +764,49 @@ void BKE_libblock_copy_data(ID *id, const ID *id_from, const short do_action)
 }
 
 /* used everywhere in blenkernel */
-void *BKE_libblock_copy(ID *id)
+void *BKE_libblock_copy_ex(Main *bmain, ID *id)
 {
        ID *idn;
        ListBase *lb;
        size_t idn_len;
 
-       lb= which_libbase(G.main, GS(id->name));
-       idn= BKE_libblock_alloc(lb, GS(id->name), id->name+2);
+       lb = which_libbase(bmain, GS(id->name));
+       idn = BKE_libblock_alloc(lb, GS(id->name), id->name + 2);
 
        assert(idn != NULL);
 
-       idn_len= MEM_allocN_len(idn);
+       idn_len = MEM_allocN_len(idn);
        if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */
-               const char *cp= (const char *)id;
-               char *cpn= (char *)idn;
+               const char *cp = (const char *)id;
+               char *cpn = (char *)idn;
 
-               memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID));
+               memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
        }
        
-       id->newid= idn;
+       id->newid = idn;
        idn->flag |= LIB_NEW;
 
-       BKE_libblock_copy_data(idn, id, FALSE);
+       BKE_libblock_copy_data(idn, id, false);
        
        return idn;
 }
 
-static void BKE_library_free(Library *UNUSED(lib))
+void *BKE_libblock_copy(ID *id)
 {
-       /* no freeing needed for libraries yet */
+       return BKE_libblock_copy_ex(G.main, id);
 }
 
-static void (*free_windowmanager_cb)(bContext *, wmWindowManager *)= NULL;
+static void BKE_library_free(Library *lib)
+{
+       if (lib->packedfile)
+               freePackedFile(lib->packedfile);
+}
+
+static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL;
 
 void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) )
 {
-       free_windowmanager_cb= func;
+       free_windowmanager_cb = func;
 }
 
 static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
@@ -769,16 +815,16 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata
        FCurve *fcu;
 
        /* find the driver this belongs to and update it */
-       for (fcu=adt->drivers.first; fcu; fcu=fcu->next) {
-               driver= fcu->driver;
+       for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+               driver = fcu->driver;
                
                if (driver) {
                        DriverVar *dvar;
-                       for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
+                       for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
                                DRIVER_TARGETS_USED_LOOPER(dvar) 
                                {
                                        if (dtar->id == userdata)
-                                               dtar->id= NULL;
+                                               dtar->id = NULL;
                                }
                                DRIVER_TARGETS_LOOPER_END
                        }
@@ -786,17 +832,30 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata
        }
 }
 
+void BKE_libblock_free_data(ID *id)
+{
+       Main *bmain = G.main;  /* should eventually be an arg */
+       
+       if (id->properties) {
+               IDP_FreeProperty(id->properties);
+               MEM_freeN(id->properties);
+       }
+       
+       /* this ID may be a driver target! */
+       BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id);
+}
 
 /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */
 void BKE_libblock_free(ListBase *lb, void *idv)
 {
-       ID *id= idv;
+       Main *bmain = G.main;  /* should eventually be an arg */
+       ID *id = idv;
 
 #ifdef WITH_PYTHON
        BPY_id_release(id);
 #endif
 
-       switch ( GS(id->name) ) {       /* GetShort from util.h */
+       switch (GS(id->name) ) {    /* GetShort from util.h */
                case ID_SCE:
                        BKE_scene_free((Scene *)id);
                        break;
@@ -813,7 +872,7 @@ void BKE_libblock_free(ListBase *lb, void *idv)
                        BKE_curve_free((Curve *)id);
                        break;
                case ID_MB:
-                       BKE_metaball_free((MetaBall *)id);
+                       BKE_mball_free((MetaBall *)id);
                        break;
                case ID_MA:
                        BKE_material_free((Material *)id);
@@ -852,7 +911,7 @@ void BKE_libblock_free(ListBase *lb, void *idv)
                        BKE_text_free((Text *)id);
                        break;
                case ID_SCRIPT:
-                       //XXX free_script((Script *)id);
+                       /* deprecated */
                        break;
                case ID_SPK:
                        BKE_speaker_free((Speaker *)id);
@@ -888,33 +947,30 @@ void BKE_libblock_free(ListBase *lb, void *idv)
                case ID_MC:
                        BKE_movieclip_free((MovieClip *)id);
                        break;
-       }
-
-       if (id->properties) {
-               IDP_FreeProperty(id->properties);
-               MEM_freeN(id->properties);
+               case ID_MSK:
+                       BKE_mask_free(bmain, (Mask *)id);
+                       break;
        }
 
        BLI_remlink(lb, id);
 
-       /* this ID may be a driver target! */
-       BKE_animdata_main_cb(G.main, animdata_dtar_clear_cb, (void *)id);
+       BKE_libblock_free_data(id);
 
        MEM_freeN(id);
 }
 
-void BKE_libblock_free_us(ListBase *lb, void *idv)             /* test users */
+void BKE_libblock_free_us(ListBase *lb, void *idv)      /* test users */
 {
-       ID *id= idv;
+       ID *id = idv;
        
        id->us--;
 
-       if (id->us<0) {
+       if (id->us < 0) {
                if (id->lib) printf("ERROR block %s %s users %d\n", id->lib->name, id->name, id->us);
                else printf("ERROR block %s users %d\n", id->name, id->us);
        }
-       if (id->us==0) {
-               if ( GS(id->name)==ID_OB ) BKE_object_unlink((Object *)id);
+       if (id->us == 0) {
+               if (GS(id->name) == ID_OB) BKE_object_unlink((Object *)id);
                
                BKE_libblock_free(lb, id);
        }
@@ -927,13 +983,55 @@ void free_main(Main *mainvar)
        ListBase *lbarray[MAX_LIBARRAY];
        int a;
 
-       a= set_listbasepointers(mainvar, lbarray);
+       a = set_listbasepointers(mainvar, lbarray);
        while (a--) {
-               ListBase *lb= lbarray[a];
+               ListBase *lb = lbarray[a];
                ID *id;
                
-               while ( (id= lb->first) ) {
+               while ( (id = lb->first) ) {
+#if 1
                        BKE_libblock_free(lb, id);
+#else
+                       /* errors freeing ID's can be hard to track down,
+                        * enable this so valgrind will give the line number in its error log */
+                       switch (a) {
+                               case   0: BKE_libblock_free(lb, id); break;
+                               case   1: BKE_libblock_free(lb, id); break;
+                               case   2: BKE_libblock_free(lb, id); break;
+                               case   3: BKE_libblock_free(lb, id); break;
+                               case   4: BKE_libblock_free(lb, id); break;
+                               case   5: BKE_libblock_free(lb, id); break;
+                               case   6: BKE_libblock_free(lb, id); break;
+                               case   7: BKE_libblock_free(lb, id); break;
+                               case   8: BKE_libblock_free(lb, id); break;
+                               case   9: BKE_libblock_free(lb, id); break;
+                               case  10: BKE_libblock_free(lb, id); break;
+                               case  11: BKE_libblock_free(lb, id); break;
+                               case  12: BKE_libblock_free(lb, id); break;
+                               case  13: BKE_libblock_free(lb, id); break;
+                               case  14: BKE_libblock_free(lb, id); break;
+                               case  15: BKE_libblock_free(lb, id); break;
+                               case  16: BKE_libblock_free(lb, id); break;
+                               case  17: BKE_libblock_free(lb, id); break;
+                               case  18: BKE_libblock_free(lb, id); break;
+                               case  19: BKE_libblock_free(lb, id); break;
+                               case  20: BKE_libblock_free(lb, id); break;
+                               case  21: BKE_libblock_free(lb, id); break;
+                               case  22: BKE_libblock_free(lb, id); break;
+                               case  23: BKE_libblock_free(lb, id); break;
+                               case  24: BKE_libblock_free(lb, id); break;
+                               case  25: BKE_libblock_free(lb, id); break;
+                               case  26: BKE_libblock_free(lb, id); break;
+                               case  27: BKE_libblock_free(lb, id); break;
+                               case  28: BKE_libblock_free(lb, id); break;
+                               case  29: BKE_libblock_free(lb, id); break;
+                               case  30: BKE_libblock_free(lb, id); break;
+                               case  31: BKE_libblock_free(lb, id); break;
+                               case  32: BKE_libblock_free(lb, id); break;
+                               default:
+                                       BLI_assert(0);
+                       }
+#endif
                }
        }
 
@@ -943,84 +1041,85 @@ void free_main(Main *mainvar)
 /* ***************** ID ************************ */
 
 
-ID *find_id(const char *type, const char *name)                /* type: "OB" or "MA" etc */
+ID *BKE_libblock_find_name(const short type, const char *name)      /* type: "OB" or "MA" etc */
 {
-       ListBase *lb= which_libbase(G.main, GS(type));
+       ListBase *lb = which_libbase(G.main, type);
+       BLI_assert(lb != NULL);
        return BLI_findstring(lb, name, offsetof(ID, name) + 2);
 }
 
 static void get_flags_for_id(ID *id, char *buf) 
 {
-       int isfake= id->flag & LIB_FAKEUSER;
-       int isnode=0;
-               /* Writeout the flags for the entry, note there
-                * is a small hack that writes 5 spaces instead
-                * of 4 if no flags are displayed... this makes
-                * things usually line up ok - better would be
-                * to have that explicit, oh well - zr
-                */
+       int isfake = id->flag & LIB_FAKEUSER;
+       int isnode = 0;
+       /* Writeout the flags for the entry, note there
+        * is a small hack that writes 5 spaces instead
+        * of 4 if no flags are displayed... this makes
+        * things usually line up ok - better would be
+        * to have that explicit, oh well - zr
+        */
 
-       if (GS(id->name)==ID_MA)
-               isnode= ((Material *)id)->use_nodes;
-       if (GS(id->name)==ID_TE)
-               isnode= ((Tex *)id)->use_nodes;
+       if (GS(id->name) == ID_MA)
+               isnode = ((Material *)id)->use_nodes;
+       if (GS(id->name) == ID_TE)
+               isnode = ((Tex *)id)->use_nodes;
        
-       if (id->us<0)
+       if (id->us < 0)
                strcpy(buf, "-1W ");
        else if (!id->lib && !isfake && id->us && !isnode)
                strcpy(buf, "     ");
        else if (isnode)
-               sprintf(buf, "%c%cN%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
+               sprintf(buf, "%c%cN%c ", id->lib ? 'L' : ' ', isfake ? 'F' : ' ', (id->us == 0) ? 'O' : ' ');
        else
-               sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
+               sprintf(buf, "%c%c%c ", id->lib ? 'L' : ' ', isfake ? 'F' : ' ', (id->us == 0) ? 'O' : ' ');
 }
 
 #define IDPUP_NO_VIEWER 1
 
 static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int hideflag)
 {
-       int i, nids= BLI_countlist(lb);
+       int i, nids = BLI_countlist(lb);
                
-       if (nr) *nr= -1;
+       if (nr) *nr = -1;
        
-       if (nr && nids>MAX_IDPUP) {
+       if (nr && nids > MAX_IDPUP) {
                BLI_dynstr_append(pupds, "DataBrowse %x-2");
-               *nr= -2;
+               *nr = -2;
        }
        else {
                ID *id;
                
-               for (i=0, id= lb->first; id; id= id->next, i++) {
+               for (i = 0, id = lb->first; id; id = id->next, i++) {
                        char numstr[32];
                        
-                       if (nr && id==link) *nr= i+1;
+                       if (nr && id == link) *nr = i + 1;
 
-                       if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.')
+                       if (U.uiflag & USER_HIDE_DOT && id->name[2] == '.')
                                continue;
                        if (hideflag & IDPUP_NO_VIEWER)
-                               if (GS(id->name)==ID_IM)
-                                       if ( ((Image *)id)->source==IMA_SRC_VIEWER )
+                               if (GS(id->name) == ID_IM)
+                                       if ( ((Image *)id)->source == IMA_SRC_VIEWER)
                                                continue;
                        
                        get_flags_for_id(id, numstr);
                                
                        BLI_dynstr_append(pupds, numstr);
-                       BLI_dynstr_append(pupds, id->name+2);
-                       BLI_snprintf(numstr, sizeof(numstr), "%%x%d", i+1);
+                       BLI_dynstr_append(pupds, id->name + 2);
+                       BLI_snprintf(numstr, sizeof(numstr), "%%x%d", i + 1);
                        BLI_dynstr_append(pupds, numstr);
                        
                        /* icon */
                        switch (GS(id->name)) {
-                       case ID_MA: /* fall through */
-                       case ID_TE: /* fall through */
-                       case ID_IM: /* fall through */
-                       case ID_WO: /* fall through */
-                       case ID_LA: /* fall through */
-                               BLI_snprintf(numstr, sizeof(numstr), "%%i%d", BKE_icon_getid(id));
-                               BLI_dynstr_append(pupds, numstr);
-                               break;
-                       default:
-                               break;
+                               case ID_MA: /* fall through */
+                               case ID_TE: /* fall through */
+                               case ID_IM: /* fall through */
+                               case ID_WO: /* fall through */
+                               case ID_LA: /* fall through */
+                                       BLI_snprintf(numstr, sizeof(numstr), "%%i%d", BKE_icon_getid(id));
+                                       BLI_dynstr_append(pupds, numstr);
+                                       break;
+                               default:
+                                       break;
                        }
                        
                        if (id->next)
@@ -1031,10 +1130,10 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor
 
 
 /* used by headerbuttons.c buttons.c editobject.c editseq.c */
-/* if nr==NULL no MAX_IDPUP, this for non-header browsing */
+/* if (nr == NULL) no MAX_IDPUP, this for non-header browsing */
 void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
 {
-       DynStr *pupds= BLI_dynstr_new();
+       DynStr *pupds = BLI_dynstr_new();
 
        if (title) {
                BLI_dynstr_append(pupds, title);
@@ -1049,7 +1148,7 @@ void IDnames_to_pupstring(const char **str, const char *title, const char *extra
 
        IDnames_to_dyn_pupstring(pupds, lb, link, nr, 0);
        
-       *str= BLI_dynstr_get_cstring(pupds);
+       *str = BLI_dynstr_get_cstring(pupds);
        BLI_dynstr_free(pupds);
 }
 
@@ -1057,7 +1156,7 @@ void IDnames_to_pupstring(const char **str, const char *title, const char *extra
 #if 0 /* unused */
 void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
 {
-       DynStr *pupds= BLI_dynstr_new();
+       DynStr *pupds = BLI_dynstr_new();
        
        if (title) {
                BLI_dynstr_append(pupds, title);
@@ -1072,7 +1171,7 @@ void IMAnames_to_pupstring(const char **str, const char *title, const char *extr
        
        IDnames_to_dyn_pupstring(pupds, lb, link, nr, IDPUP_NO_VIEWER);
        
-       *str= BLI_dynstr_get_cstring(pupds);
+       *str = BLI_dynstr_get_cstring(pupds);
        BLI_dynstr_free(pupds);
 }
 #endif
@@ -1082,40 +1181,40 @@ void id_sort_by_name(ListBase *lb, ID *id)
        ID *idtest;
        
        /* insert alphabetically */
-       if (lb->first!=lb->last) {
+       if (lb->first != lb->last) {
                BLI_remlink(lb, id);
                
-               idtest= lb->first;
+               idtest = lb->first;
                while (idtest) {
-                       if (BLI_strcasecmp(idtest->name, id->name)>0 || (idtest->lib && !id->lib)) {
+                       if (BLI_strcasecmp(idtest->name, id->name) > 0 || (idtest->lib && !id->lib)) {
                                BLI_insertlinkbefore(lb, idtest, id);
                                break;
                        }
-                       idtest= idtest->next;
+                       idtest = idtest->next;
                }
                /* as last */
-               if (idtest==NULL) {
+               if (idtest == NULL) {
                        BLI_addtail(lb, id);
                }
        }
        
 }
 
-/*
+/**
  * Check to see if there is an ID with the same name as 'name'.
  * Returns the ID if so, if not, returns NULL
  */
 static ID *is_dupid(ListBase *lb, ID *id, const char *name)
 {
-       ID *idtest=NULL;
+       ID *idtest = NULL;
        
-       for ( idtest = lb->first; idtest; idtest = idtest->next ) {
+       for (idtest = lb->first; idtest; idtest = idtest->next) {
                /* if idtest is not a lib */ 
-               if ( id != idtest && idtest->lib == NULL ) {
+               if (id != idtest && idtest->lib == NULL) {
                        /* do not test alphabetic! */
                        /* optimized */
-                       if ( idtest->name[2] == name[0] ) {
-                               if (strcmp(name, idtest->name+2)==0) break;
+                       if (idtest->name[2] == name[0]) {
+                               if (strcmp(name, idtest->name + 2) == 0) break;
                        }
                }
        }
@@ -1123,89 +1222,107 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name)
        return idtest;
 }
 
-/* 
+/**
  * Check to see if an ID name is already used, and find a new one if so.
- * Return 1 if created a new name (returned in name).
+ * Return true if created a new name (returned in name).
  *
  * Normally the ID that's being check is already in the ListBase, so ID *id
  * points at the new entry.  The Python Library module needs to know what
  * the name of a datablock will be before it is appended; in this case ID *id
- * id is NULL;
+ * id is NULL
  */
 
-static int check_for_dupid(ListBase *lb, ID *id, char *name)
+static bool check_for_dupid(ListBase *lb, ID *id, char *name)
 {
        ID *idtest;
-       int nr= 0, nrtest, a, left_len;
-       char in_use[64]; /* use as a boolean array, unrelated to name length */
+       int nr = 0, nrtest, a, left_len;
+#define MAX_IN_USE 64
+       bool in_use[MAX_IN_USE];
+       /* to speed up finding unused numbers within [1 .. MAX_IN_USE - 1] */
 
        char left[MAX_ID_NAME + 8], leftest[MAX_ID_NAME + 8];
 
        /* make sure input name is terminated properly */
-       /* if ( strlen(name) > MAX_ID_NAME-3 ) name[MAX_ID_NAME-3]= 0; */
+       /* if ( strlen(name) > MAX_ID_NAME-3 ) name[MAX_ID_NAME-3] = 0; */
        /* removed since this is only ever called from one place - campbell */
 
-       while (1) {
+       while (true) {
 
                /* phase 1: id already exists? */
                idtest = is_dupid(lb, id, name);
 
                /* if there is no double, done */
-               if ( idtest == NULL ) return 0;
+               if (idtest == NULL) return false;
 
                /* we have a dup; need to make a new name */
-               /* quick check so we can reuse one of first 64 ids if vacant */
-               memset(in_use, 0, sizeof(in_use));
+               /* quick check so we can reuse one of first MAX_IN_USE - 1 ids if vacant */
+               memset(in_use, false, sizeof(in_use));
 
                /* get name portion, number portion ("name.number") */
-               left_len= BLI_split_name_num(left, &nr, name, '.');
+               left_len = BLI_split_name_num(left, &nr, name, '.');
 
                /* if new name will be too long, truncate it */
-               if (nr > 999 && left_len > (MAX_ID_NAME - 8)) {
-                       left[MAX_ID_NAME - 8]= 0;
-                       left_len= MAX_ID_NAME - 8;
+               if (nr > 999 && left_len > (MAX_ID_NAME - 8)) {  /* assumption: won't go beyond 9999 */
+                       left[MAX_ID_NAME - 8] = 0;
+                       left_len = MAX_ID_NAME - 8;
                }
                else if (left_len > (MAX_ID_NAME - 7)) {
-                       left[MAX_ID_NAME - 7]= 0;
-                       left_len= MAX_ID_NAME - 7;
+                       left[MAX_ID_NAME - 7] = 0;
+                       left_len = MAX_ID_NAME - 7;
                }
 
-               for (idtest= lb->first; idtest; idtest= idtest->next) {
-                       if (            (id != idtest) &&
-                                       (idtest->lib == NULL) &&
-                                       (*name == *(idtest->name+2)) &&
-                                       (strncmp(name, idtest->name+2, left_len)==0) &&
-                                       (BLI_split_name_num(leftest, &nrtest, idtest->name+2, '.') == left_len)
-                       ) {
-                               if (nrtest < sizeof(in_use))
-                                       in_use[nrtest]= 1;      /* mark as used */
+               for (idtest = lb->first; idtest; idtest = idtest->next) {
+                       if ( (id != idtest) &&
+                            (idtest->lib == NULL) &&
+                            (*name == *(idtest->name + 2)) &&
+                            (strncmp(name, idtest->name + 2, left_len) == 0) &&
+                            (BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len)
+                            )
+                       {
+                               /* will get here at least once, otherwise is_dupid call above would have returned NULL */
+                               if (nrtest < MAX_IN_USE)
+                                       in_use[nrtest] = true;  /* mark as used */
                                if (nr <= nrtest)
-                                       nr= nrtest+1;           /* track largest unused */
+                                       nr = nrtest + 1;    /* track largest unused */
                        }
                }
+               /* At this point, nr will be at least 1. */
+               BLI_assert(nr >= 1);
 
                /* decide which value of nr to use */
-               for (a=0; a < sizeof(in_use); a++) {
-                       if (a>=nr) break;       /* stop when we've check up to biggest */
-                       if ( in_use[a]==0 ) { /* found an unused value */
+               for (a = 0; a < MAX_IN_USE; a++) {
+                       if (a >= nr) break;  /* stop when we've checked up to biggest */  /* redundant check */
+                       if (!in_use[a]) { /* found an unused value */
                                nr = a;
+                               /* can only be zero if all potential duplicate names had
+                                * nonzero numeric suffixes, which means name itself has
+                                * nonzero numeric suffix (else no name conflict and wouldn't
+                                * have got here), which means name[left_len] is not a null */
                                break;
                        }
                }
+               /* At this point, nr is either the lowest unused number within [0 .. MAX_IN_USE - 1],
+                * or 1 greater than the largest used number if all those low ones are taken.
+                * We can't be bothered to look for the lowest unused number beyond (MAX_IN_USE - 1). */
 
                /* If the original name has no numeric suffix, 
                 * rather than just chopping and adding numbers, 
                 * shave off the end chars until we have a unique name.
                 * Check the null terminators match as well so we don't get Cube.000 -> Cube.00 */
-               if (nr==0 && name[left_len]== '\0') {
-                       int len = left_len-1;
-                       idtest= is_dupid(lb, id, name);
+               if (nr == 0 && name[left_len] == '\0') {
+                       int len;
+                       /* FIXME: this code will never be executed, because either nr will be
+                        * at least 1, or name will not end at left_len! */
+                       BLI_assert(0);
+
+                       len = left_len - 1;
+                       idtest = is_dupid(lb, id, name);
                        
-                       while (idtest && len> 1) {
+                       while (idtest && len > 1) {
                                name[len--] = '\0';
-                               idtest= is_dupid(lb, id, name);
+                               idtest = is_dupid(lb, id, name);
                        }
-                       if (idtest == NULL) return 1;
+                       if (idtest == NULL) return true;
                        /* otherwise just continue and use a number suffix */
                }
                
@@ -1219,38 +1336,40 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
                /* this format specifier is from hell... */
                BLI_snprintf(name, sizeof(id->name) - 2, "%s.%.3d", left, nr);
 
-               return 1;
+               return true;
        }
+
+#undef MAX_IN_USE
 }
 
 /*
  * Only for local blocks: external en indirect blocks already have a
  * unique ID.
  *
- * return 1: created a new name
+ * return true: created a new name
  */
 
-int new_id(ListBase *lb, ID *id, const char *tname)
+bool new_id(ListBase *lb, ID *id, const char *tname)
 {
-       int result;
-       char name[MAX_ID_NAME-2];
+       bool result;
+       char name[MAX_ID_NAME - 2];
 
        /* if library, don't rename */
-       if (id->lib) return 0;
+       if (id->lib) return false;
 
        /* if no libdata given, look up based on ID */
-       if (lb==NULL) lb= which_libbase(G.main, GS(id->name));
+       if (lb == NULL) lb = which_libbase(G.main, GS(id->name));
 
        /* if no name given, use name of current ID
         * else make a copy (tname args can be const) */
-       if (tname==NULL)
-               tname= id->name+2;
+       if (tname == NULL)
+               tname = id->name + 2;
 
-       strncpy(name, tname, sizeof(name)-1);
+       strncpy(name, tname, sizeof(name) - 1);
 
        /* if result > MAX_ID_NAME-3, strncpy don't put the final '\0' to name.
         * easier to assign each time then to check if its needed */
-       name[sizeof(name)-1]= 0;
+       name[sizeof(name) - 1] = 0;
 
        if (name[0] == '\0') {
                /* disallow empty names */
@@ -1263,14 +1382,14 @@ int new_id(ListBase *lb, ID *id, const char *tname)
        }
 
        result = check_for_dupid(lb, id, name);
-       strcpy(id->name+2, name);
+       strcpy(id->name + 2, name);
 
        /* This was in 2.43 and previous releases
         * however all data in blender should be sorted, not just duplicate names
         * sorting should not hurt, but noting just incause it alters the way other
         * functions work, so sort every time */
 #if 0
-       if ( result )
+       if (result)
                id_sort_by_name(lb, id);
 #endif
 
@@ -1285,8 +1404,8 @@ void id_clear_lib_data(Main *bmain, ID *id)
 {
        BKE_id_lib_local_paths(bmain, id->lib, id);
 
-       id->lib= NULL;
-       id->flag= LIB_LOCAL;
+       id->lib = NULL;
+       id->flag = LIB_LOCAL;
        new_id(which_libbase(bmain, GS(id->name)), id, NULL);
 }
 
@@ -1297,21 +1416,20 @@ void clear_id_newpoins(void)
        ID *id;
        int a;
 
-       a= set_listbasepointers(G.main, lbarray);
+       a = set_listbasepointers(G.main, lbarray);
        while (a--) {
-               id= lbarray[a]->first;
+               id = lbarray[a]->first;
                while (id) {
-                       id->newid= NULL;
+                       id->newid = NULL;
                        id->flag &= ~LIB_NEW;
-                       id= id->next;
+                       id = id->next;
                }
        }
 }
 
-#define LIBTAG(a)      if (a && a->id.lib) {a->id.flag &=~LIB_INDIRECT; a->id.flag |= LIB_EXTERN;}
-
 static void lib_indirect_test_id(ID *id, Library *lib)
 {
+#define LIBTAG(a)   if (a && a->id.lib) { a->id.flag &= ~LIB_INDIRECT; a->id.flag |= LIB_EXTERN; } (void)0
        
        if (id->lib) {
                /* datablocks that were indirectly related are now direct links
@@ -1322,47 +1440,49 @@ static void lib_indirect_test_id(ID *id, Library *lib)
                return;
        }
        
-       if (GS(id->name)==ID_OB) {              
-               Object *ob= (Object *)id;
+       if (GS(id->name) == ID_OB) {
+               Object *ob = (Object *)id;
                Mesh *me;
 
                int a;
 
-#if 0  /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
-               // XXX old animation system! --------------------------------------
+#if 0   /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
+               /* XXX old animation system! -------------------------------------- */
                {
                        bActionStrip *strip;
-                       for (strip=ob->nlastrips.first; strip; strip=strip->next) {
+                       for (strip = ob->nlastrips.first; strip; strip = strip->next) {
                                LIBTAG(strip->object);
                                LIBTAG(strip->act);
                                LIBTAG(strip->ipo);
                        }
                }
-               // XXX: new animation system needs something like this?
+               /* XXX: new animation system needs something like this? */
 #endif
 
-               for (a=0; a<ob->totcol; a++) {
+               for (a = 0; a < ob->totcol; a++) {
                        LIBTAG(ob->mat[a]);
                }
        
                LIBTAG(ob->dup_group);
                LIBTAG(ob->proxy);
                
-               me= ob->data;
+               me = ob->data;
                LIBTAG(me);
        }
+
+#undef LIBTAG
 }
 
 void tag_main_lb(ListBase *lb, const short tag)
 {
        ID *id;
        if (tag) {
-               for (id= lb->first; id; id= id->next) {
+               for (id = lb->first; id; id = id->next) {
                        id->flag |= LIB_DOIT;
                }
        }
        else {
-               for (id= lb->first; id; id= id->next) {
+               for (id = lb->first; id; id = id->next) {
                        id->flag &= ~LIB_DOIT;
                }
        }
@@ -1370,7 +1490,7 @@ void tag_main_lb(ListBase *lb, const short tag)
 
 void tag_main_idcode(struct Main *mainvar, const short type, const short tag)
 {
-       ListBase *lb= which_libbase(mainvar, type);
+       ListBase *lb = which_libbase(mainvar, type);
 
        tag_main_lb(lb, tag);
 }
@@ -1380,7 +1500,7 @@ void tag_main(struct Main *mainvar, const short tag)
        ListBase *lbarray[MAX_LIBARRAY];
        int a;
 
-       a= set_listbasepointers(mainvar, lbarray);
+       a = set_listbasepointers(mainvar, lbarray);
        while (a--) {
                tag_main_lb(lbarray[a], tag);
        }
@@ -1388,29 +1508,29 @@ void tag_main(struct Main *mainvar, const short tag)
 
 /* if lib!=NULL, only all from lib local
  * bmain is almost certainly G.main */
-void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only)
+void BKE_library_make_local(Main *bmain, Library *lib, bool untagged_only)
 {
-       ListBase *lbarray[MAX_LIBARRAY], tempbase={NULL, NULL};
+       ListBase *lbarray[MAX_LIBARRAY];
        ID *id, *idn;
        int a;
 
-       a= set_listbasepointers(bmain, lbarray);
+       a = set_listbasepointers(bmain, lbarray);
        while (a--) {
-               id= lbarray[a]->first;
+               id = lbarray[a]->first;
                
                while (id) {
-                       id->newid= NULL;
-                       idn= id->next;          /* id is possibly being inserted again */
+                       id->newid = NULL;
+                       idn = id->next;      /* id is possibly being inserted again */
                        
                        /* The check on the second line (LIB_PRE_EXISTING) is done so its
                         * possible to tag data you don't want to be made local, used for
                         * appending data, so any libdata already linked wont become local
                         * (very nasty to discover all your links are lost after appending)  
                         * */
-                       if (id->flag & (LIB_EXTERN|LIB_INDIRECT|LIB_NEW) &&
-                         (untagged_only==0 || !(id->flag & LIB_PRE_EXISTING)))
+                       if (id->flag & (LIB_EXTERN | LIB_INDIRECT | LIB_NEW) &&
+                           ((untagged_only == false) || !(id->flag & LIB_PRE_EXISTING)))
                        {
-                               if (lib==NULL || id->lib==lib) {
+                               if (lib == NULL || id->lib == lib) {
                                        if (id->lib) {
                                                id_clear_lib_data(bmain, id); /* sets 'id->flag' */
 
@@ -1419,25 +1539,17 @@ void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only)
                                                id_sort_by_name(lbarray[a], id);
                                        }
                                        else {
-                                               id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW);
+                                               id->flag &= ~(LIB_EXTERN | LIB_INDIRECT | LIB_NEW);
                                        }
                                }
                        }
-                       id= idn;
-               }
-               
-               /* patch2: make it aphabetically */
-               while ( (id=tempbase.first) ) {
-                       BLI_remlink(&tempbase, id);
-                       BLI_addtail(lbarray[a], id);
-                       new_id(lbarray[a], id, NULL);
+                       id = idn;
                }
        }
 
-       /* patch 3: make sure library data isn't indirect falsely... */
-       a= set_listbasepointers(bmain, lbarray);
+       a = set_listbasepointers(bmain, lbarray);
        while (a--) {
-               for (id= lbarray[a]->first; id; id=id->next)
+               for (id = lbarray[a]->first; id; id = id->next)
                        lib_indirect_test_id(id, lib);
        }
 }
@@ -1450,54 +1562,41 @@ void test_idbutton(char *name)
        ID *idtest;
        
 
-       lb= which_libbase(G.main, GS(name-2) );
-       if (lb==NULL) return;
+       lb = which_libbase(G.main, GS(name) );
+       if (lb == NULL) return;
        
        /* search for id */
-       idtest= BLI_findstring(lb, name, offsetof(ID, name) + 2);
+       idtest = BLI_findstring(lb, name + 2, offsetof(ID, name) + 2);
 
-       if (idtest) if ( new_id(lb, idtest, name)==0 ) id_sort_by_name(lb, idtest);
-}
-
-void text_idbutton(struct ID *id, char *text)
-{
-       if (id) {
-               if (GS(id->name)==ID_SCE)
-                       strcpy(text, "SCE: ");
-               else if (GS(id->name)==ID_SCR)
-                       strcpy(text, "SCR: ");
-               else if (GS(id->name)==ID_MA && ((Material*)id)->use_nodes)
-                       strcpy(text, "NT: ");
-               else {
-                       text[0]= id->name[0];
-                       text[1]= id->name[1];
-                       text[2]= ':';
-                       text[3]= ' ';
-                       text[4]= 0;
-               }
-       }
-       else {
-               text[0]= '\0';
+       if (idtest && !new_id(lb, idtest, name + 2)) {
+               id_sort_by_name(lb, idtest);
        }
 }
 
+/**
+ * Sets the name of a block to name, suitably adjusted for uniqueness.
+ */
 void rename_id(ID *id, const char *name)
 {
        ListBase *lb;
 
-       BLI_strncpy(id->name+2, name, sizeof(id->name)-2);
-       lb= which_libbase(G.main, GS(id->name) );
+       BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
+       lb = which_libbase(G.main, GS(id->name) );
        
-       new_id(lb, id, name);                           
+       new_id(lb, id, name);
 }
 
-void name_uiprefix_id(char *name, ID *id)
+/**
+ * Returns in name the name of the block, with a 3-character prefix prepended
+ * indicating whether it comes from a library, has a fake user, or no users.
+ */
+void name_uiprefix_id(char *name, const ID *id)
 {
-       name[0] = id->lib ? 'L':' ';
-       name[1] = id->flag & LIB_FAKEUSER ? 'F': (id->us==0)?'0':' ';
+       name[0] = id->lib ? 'L' : ' ';
+       name[1] = id->flag & LIB_FAKEUSER ? 'F' : (id->us == 0) ? '0' : ' ';
        name[2] = ' ';
 
-       strcpy(name+3, id->name+2);
+       strcpy(name + 3, id->name + 2);
 }
 
 void BKE_library_filepath_set(Library *lib, const char *filepath)
@@ -1512,13 +1611,13 @@ void BKE_library_filepath_set(Library *lib, const char *filepath)
 
        /* not essential but set filepath is an absolute copy of value which
         * is more useful if its kept in sync */
-       if (strncmp(lib->filepath, "//", 2) == 0) {
+       if (BLI_path_is_rel(lib->filepath)) {
                /* note that the file may be unsaved, in this case, setting the
                 * filepath on an indirectly linked path is not allowed from the
                 * outliner, and its not really supported but allow from here for now
                 * since making local could cause this to be directly linked - campbell
                 */
-               const char *basepath= lib->parent ? lib->parent->filepath : G.main->name;
+               const char *basepath = lib->parent ? lib->parent->filepath : G.main->name;
                BLI_path_abs(lib->filepath, basepath);
        }
 }