Blender  V2.59
library.c
Go to the documentation of this file.
00001 /* 
00002  * $Id: library.c 36411 2011-05-01 10:14:09Z campbellbarton $
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) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 /*
00036  *  Contains management of ID's and libraries
00037  *  allocate and free of all library data
00038  * 
00039  */
00040 
00041 
00042 #include <stdio.h>
00043 #include <ctype.h>
00044 #include <string.h>
00045 #include <stdlib.h>
00046 #include <stddef.h>
00047 #include <assert.h>
00048 
00049 #include "MEM_guardedalloc.h"
00050 
00051 /* all types are needed here, in order to do memory operations */
00052 #include "DNA_anim_types.h"
00053 #include "DNA_armature_types.h"
00054 #include "DNA_brush_types.h"
00055 #include "DNA_camera_types.h"
00056 #include "DNA_group_types.h"
00057 #include "DNA_ipo_types.h"
00058 #include "DNA_key_types.h"
00059 #include "DNA_lamp_types.h"
00060 #include "DNA_lattice_types.h"
00061 #include "DNA_material_types.h"
00062 #include "DNA_mesh_types.h"
00063 #include "DNA_meta_types.h"
00064 #include "DNA_nla_types.h"
00065 #include "DNA_node_types.h"
00066 #include "DNA_scene_types.h"
00067 #include "DNA_screen_types.h"
00068 #include "DNA_sound_types.h"
00069 #include "DNA_text_types.h"
00070 #include "DNA_vfont_types.h"
00071 #include "DNA_windowmanager_types.h"
00072 #include "DNA_world_types.h"
00073 #include "DNA_gpencil_types.h"
00074 
00075 #include "BLI_blenlib.h"
00076 #include "BLI_dynstr.h"
00077 #include "BLI_utildefines.h"
00078 
00079 
00080 #include "BKE_animsys.h"
00081 #include "BKE_context.h"
00082 #include "BKE_library.h"
00083 #include "BKE_main.h"
00084 #include "BKE_global.h"
00085 #include "BKE_sound.h"
00086 #include "BKE_object.h"
00087 #include "BKE_screen.h"
00088 #include "BKE_mesh.h"
00089 #include "BKE_material.h"
00090 #include "BKE_curve.h"
00091 #include "BKE_mball.h"
00092 #include "BKE_text.h"
00093 #include "BKE_texture.h"
00094 #include "BKE_scene.h"
00095 #include "BKE_icons.h"
00096 #include "BKE_image.h"
00097 #include "BKE_ipo.h"
00098 #include "BKE_key.h"
00099 #include "BKE_world.h"
00100 #include "BKE_font.h"
00101 #include "BKE_group.h"
00102 #include "BKE_lattice.h"
00103 #include "BKE_armature.h"
00104 #include "BKE_action.h"
00105 #include "BKE_node.h"
00106 #include "BKE_brush.h"
00107 #include "BKE_idprop.h"
00108 #include "BKE_particle.h"
00109 #include "BKE_gpencil.h"
00110 #include "BKE_fcurve.h"
00111 
00112 #ifdef WITH_PYTHON
00113 #include "BPY_extern.h"
00114 #endif
00115 
00116 #define MAX_IDPUP               60      /* was 24 */
00117 
00118 /* GS reads the memory pointed at in a specific ordering. 
00119    only use this definition, makes little and big endian systems
00120    work fine, in conjunction with MAKE_ID */
00121 
00122 /* from blendef: */
00123 #define GS(a)   (*((short *)(a)))
00124 
00125 /* ************* general ************************ */
00126 
00127 void id_lib_extern(ID *id)
00128 {
00129         if(id) {
00130                 if(id->flag & LIB_INDIRECT) {
00131                         id->flag -= LIB_INDIRECT;
00132                         id->flag |= LIB_EXTERN;
00133                 }
00134         }
00135 }
00136 
00137 void id_us_plus(ID *id)
00138 {
00139         if(id) {
00140                 id->us++;
00141                 if(id->flag & LIB_INDIRECT) {
00142                         id->flag -= LIB_INDIRECT;
00143                         id->flag |= LIB_EXTERN;
00144                 }
00145         }
00146 }
00147 
00148 void id_us_min(ID *id)
00149 {
00150         if(id) {
00151                 if(id->us<2 && (id->flag & LIB_FAKEUSER))
00152                    id->us= 1;
00153                 else if(id->us<=0)
00154                         printf("ID user decrement error: %s \n", id->name);
00155                 else
00156                         id->us--;
00157         }
00158 }
00159 
00160 int id_make_local(ID *id, int test)
00161 {
00162         if(id->flag & LIB_INDIRECT)
00163                 return 0;
00164 
00165         switch(GS(id->name)) {
00166                 case ID_SCE:
00167                         return 0; /* not implemented */
00168                 case ID_LI:
00169                         return 0; /* can't be linked */
00170                 case ID_OB:
00171                         if(!test) make_local_object((Object*)id);
00172                         return 1;
00173                 case ID_ME:
00174                         if(!test) {
00175                                 make_local_mesh((Mesh*)id);
00176                                 make_local_key(((Mesh*)id)->key);
00177                         }
00178                         return 1;
00179                 case ID_CU:
00180                         if(!test) {
00181                                 make_local_curve((Curve*)id);
00182                                 make_local_key(((Curve*)id)->key);
00183                         }
00184                         return 1;
00185                 case ID_MB:
00186                         if(!test) make_local_mball((MetaBall*)id);
00187                         return 1;
00188                 case ID_MA:
00189                         if(!test) make_local_material((Material*)id);
00190                         return 1;
00191                 case ID_TE:
00192                         if(!test) make_local_texture((Tex*)id);
00193                         return 1;
00194                 case ID_IM:
00195                         return 0; /* not implemented */
00196                 case ID_LT:
00197                         if(!test) {
00198                                 make_local_lattice((Lattice*)id);
00199                                 make_local_key(((Lattice*)id)->key);
00200                         }
00201                         return 1;
00202                 case ID_LA:
00203                         if(!test) make_local_lamp((Lamp*)id);
00204                         return 1;
00205                 case ID_CA:
00206                         if(!test) make_local_camera((Camera*)id);
00207                         return 1;
00208                 case ID_IP:
00209                         return 0; /* deprecated */
00210                 case ID_KE:
00211                         if(!test) make_local_key((Key*)id);
00212                         return 1;
00213                 case ID_WO:
00214                         if(!test) make_local_world((World*)id);
00215                         return 1;
00216                 case ID_SCR:
00217                         return 0; /* can't be linked */
00218                 case ID_VF:
00219                         return 0; /* not implemented */
00220                 case ID_TXT:
00221                         return 0; /* not implemented */
00222                 case ID_SCRIPT:
00223                         return 0; /* deprecated */
00224                 case ID_SO:
00225                         return 0; /* not implemented */
00226                 case ID_GR:
00227                         return 0; /* not implemented */
00228                 case ID_AR:
00229                         if(!test) make_local_armature((bArmature*)id);
00230                         return 1;
00231                 case ID_AC:
00232                         if(!test) make_local_action((bAction*)id);
00233                         return 1;
00234                 case ID_NT:
00235                         return 0; /* not implemented */
00236                 case ID_BR:
00237                         if(!test) make_local_brush((Brush*)id);
00238                         return 1;
00239                 case ID_PA:
00240                         if(!test) make_local_particlesettings((ParticleSettings*)id);
00241                         return 1;
00242                 case ID_WM:
00243                         return 0; /* can't be linked */
00244                 case ID_GD:
00245                         return 0; /* not implemented */
00246         }
00247 
00248         return 0;
00249 }
00250 
00251 int id_copy(ID *id, ID **newid, int test)
00252 {
00253         if(!test) *newid= NULL;
00254 
00255         /* conventions:
00256          * - make shallow copy, only this ID block
00257          * - id.us of the new ID is set to 1 */
00258         switch(GS(id->name)) {
00259                 case ID_SCE:
00260                         return 0; /* can't be copied from here */
00261                 case ID_LI:
00262                         return 0; /* can't be copied from here */
00263                 case ID_OB:
00264                         if(!test) *newid= (ID*)copy_object((Object*)id);
00265                         return 1;
00266                 case ID_ME:
00267                         if(!test) *newid= (ID*)copy_mesh((Mesh*)id);
00268                         return 1;
00269                 case ID_CU:
00270                         if(!test) *newid= (ID*)copy_curve((Curve*)id);
00271                         return 1;
00272                 case ID_MB:
00273                         if(!test) *newid= (ID*)copy_mball((MetaBall*)id);
00274                         return 1;
00275                 case ID_MA:
00276                         if(!test) *newid= (ID*)copy_material((Material*)id);
00277                         return 1;
00278                 case ID_TE:
00279                         if(!test) *newid= (ID*)copy_texture((Tex*)id);
00280                         return 1;
00281                 case ID_IM:
00282                         if(!test) *newid= (ID*)copy_image((Image*)id);
00283                         return 1;
00284                 case ID_LT:
00285                         if(!test) *newid= (ID*)copy_lattice((Lattice*)id);
00286                         return 1;
00287                 case ID_LA:
00288                         if(!test) *newid= (ID*)copy_lamp((Lamp*)id);
00289                         return 1;
00290                 case ID_CA:
00291                         if(!test) *newid= (ID*)copy_camera((Camera*)id);
00292                         return 1;
00293                 case ID_IP:
00294                         return 0; /* deprecated */
00295                 case ID_KE:
00296                         if(!test) *newid= (ID*)copy_key((Key*)id);
00297                         return 1;
00298                 case ID_WO:
00299                         if(!test) *newid= (ID*)copy_world((World*)id);
00300                         return 1;
00301                 case ID_SCR:
00302                         return 0; /* can't be copied from here */
00303                 case ID_VF:
00304                         return 0; /* not implemented */
00305                 case ID_TXT:
00306                         if(!test) *newid= (ID*)copy_text((Text*)id);
00307                         return 1;
00308                 case ID_SCRIPT:
00309                         return 0; /* deprecated */
00310                 case ID_SO:
00311                         return 0; /* not implemented */
00312                 case ID_GR:
00313                         if(!test) *newid= (ID*)copy_group((Group*)id);
00314                         return 1;
00315                 case ID_AR:
00316                         if(!test) *newid= (ID*)copy_armature((bArmature*)id);
00317                         return 1;
00318                 case ID_AC:
00319                         if(!test) *newid= (ID*)copy_action((bAction*)id);
00320                         return 1;
00321                 case ID_NT:
00322                         if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id);
00323                         return 1;
00324                 case ID_BR:
00325                         if(!test) *newid= (ID*)copy_brush((Brush*)id);
00326                         return 1;
00327                 case ID_PA:
00328                         if(!test) *newid= (ID*)psys_copy_settings((ParticleSettings*)id);
00329                         return 1;
00330                 case ID_WM:
00331                         return 0; /* can't be copied from here */
00332                 case ID_GD:
00333                         return 0; /* not implemented */
00334         }
00335         
00336         return 0;
00337 }
00338 
00339 int id_unlink(ID *id, int test)
00340 {
00341         Main *mainlib= G.main;
00342         ListBase *lb;
00343 
00344         switch(GS(id->name)) {
00345                 case ID_TXT:
00346                         if(test) return 1;
00347                         unlink_text(mainlib, (Text*)id);
00348                         break;
00349                 case ID_GR:
00350                         if(test) return 1;
00351                         unlink_group((Group*)id);
00352                         break;
00353                 case ID_OB:
00354                         if(test) return 1;
00355                         unlink_object((Object*)id);
00356                         break;
00357         }
00358 
00359         if(id->us == 0) {
00360                 if(test) return 1;
00361 
00362                 lb= which_libbase(mainlib, GS(id->name));
00363                 free_libblock(lb, id);
00364 
00365                 return 1;
00366         }
00367 
00368         return 0;
00369 }
00370 
00371 ListBase *which_libbase(Main *mainlib, short type)
00372 {
00373         switch( type ) {
00374                 case ID_SCE:
00375                         return &(mainlib->scene);
00376                 case ID_LI:
00377                         return &(mainlib->library);
00378                 case ID_OB:
00379                         return &(mainlib->object);
00380                 case ID_ME:
00381                         return &(mainlib->mesh);
00382                 case ID_CU:
00383                         return &(mainlib->curve);
00384                 case ID_MB:
00385                         return &(mainlib->mball);
00386                 case ID_MA:
00387                         return &(mainlib->mat);
00388                 case ID_TE:
00389                         return &(mainlib->tex);
00390                 case ID_IM:
00391                         return &(mainlib->image);
00392                 case ID_LT:
00393                         return &(mainlib->latt);
00394                 case ID_LA:
00395                         return &(mainlib->lamp);
00396                 case ID_CA:
00397                         return &(mainlib->camera);
00398                 case ID_IP:
00399                         return &(mainlib->ipo);
00400                 case ID_KE:
00401                         return &(mainlib->key);
00402                 case ID_WO:
00403                         return &(mainlib->world);
00404                 case ID_SCR:
00405                         return &(mainlib->screen);
00406                 case ID_VF:
00407                         return &(mainlib->vfont);
00408                 case ID_TXT:
00409                         return &(mainlib->text);
00410                 case ID_SCRIPT:
00411                         return &(mainlib->script);
00412                 case ID_SO:
00413                         return &(mainlib->sound);
00414                 case ID_GR:
00415                         return &(mainlib->group);
00416                 case ID_AR:
00417                         return &(mainlib->armature);
00418                 case ID_AC:
00419                         return &(mainlib->action);
00420                 case ID_NT:
00421                         return &(mainlib->nodetree);
00422                 case ID_BR:
00423                         return &(mainlib->brush);
00424                 case ID_PA:
00425                         return &(mainlib->particle);
00426                 case ID_WM:
00427                         return &(mainlib->wm);
00428                 case ID_GD:
00429                         return &(mainlib->gpencil);
00430         }
00431         return NULL;
00432 }
00433 
00434 /* Flag all ids in listbase */
00435 void flag_listbase_ids(ListBase *lb, short flag, short value)
00436 {
00437         ID *id;
00438         if (value) {
00439                 for(id= lb->first; id; id= id->next) id->flag |= flag;
00440         } else {
00441                 flag = ~flag;
00442                 for(id= lb->first; id; id= id->next) id->flag &= flag;
00443         }
00444 }
00445 
00446 /* Flag all ids in listbase */
00447 void flag_all_listbases_ids(short flag, short value)
00448 {
00449         ListBase *lbarray[MAX_LIBARRAY];
00450         int a;
00451         a= set_listbasepointers(G.main, lbarray);
00452         while(a--)      flag_listbase_ids(lbarray[a], flag, value);
00453 }
00454 
00455 void recalc_all_library_objects(Main *main)
00456 {
00457         Object *ob;
00458 
00459         /* flag for full recalc */
00460         for(ob=main->object.first; ob; ob=ob->id.next)
00461                 if(ob->id.lib)
00462                         ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
00463 }
00464 
00465 /* note: MAX_LIBARRAY define should match this code */
00466 int set_listbasepointers(Main *main, ListBase **lb)
00467 {
00468         int a = 0;
00469 
00470         /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last.
00471          * This is important because freeing data decreases usercounts of other datablocks,
00472          * if this data is its self freed it can crash. */
00473         lb[a++]= &(main->ipo);
00474         lb[a++]= &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith)
00475         lb[a++]= &(main->key);
00476         lb[a++]= &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */
00477         lb[a++]= &(main->nodetree);
00478         lb[a++]= &(main->image);
00479         lb[a++]= &(main->tex);
00480         lb[a++]= &(main->mat);
00481         lb[a++]= &(main->vfont);
00482         
00483         /* Important!: When adding a new object type,
00484          * the specific data should be inserted here 
00485          */
00486 
00487         lb[a++]= &(main->armature);
00488 
00489         lb[a++]= &(main->mesh);
00490         lb[a++]= &(main->curve);
00491         lb[a++]= &(main->mball);
00492 
00493         lb[a++]= &(main->latt);
00494         lb[a++]= &(main->lamp);
00495         lb[a++]= &(main->camera);
00496         
00497         lb[a++]= &(main->text);
00498         lb[a++]= &(main->sound);
00499         lb[a++]= &(main->group);
00500         lb[a++]= &(main->brush);
00501         lb[a++]= &(main->script);
00502         lb[a++]= &(main->particle);
00503 
00504         lb[a++]= &(main->world);
00505         lb[a++]= &(main->screen);
00506         lb[a++]= &(main->object);
00507         lb[a++]= &(main->scene);
00508         lb[a++]= &(main->library);
00509         lb[a++]= &(main->wm);
00510         
00511         lb[a]= NULL;
00512 
00513         return a;
00514 }
00515 
00516 /* *********** ALLOC AND FREE *****************
00517   
00518 free_libblock(ListBase *lb, ID *id )
00519         provide a list-basis and datablock, but only ID is read
00520 
00521 void *alloc_libblock(ListBase *lb, type, name)
00522         inserts in list and returns a new ID
00523 
00524  ***************************** */
00525 
00526 static ID *alloc_libblock_notest(short type)
00527 {
00528         ID *id= NULL;
00529         
00530         switch( type ) {
00531                 case ID_SCE:
00532                         id= MEM_callocN(sizeof(Scene), "scene");
00533                         break;
00534                 case ID_LI:
00535                         id= MEM_callocN(sizeof(Library), "library");
00536                         break;
00537                 case ID_OB:
00538                         id= MEM_callocN(sizeof(Object), "object");
00539                         break;
00540                 case ID_ME:
00541                         id= MEM_callocN(sizeof(Mesh), "mesh");
00542                         break;
00543                 case ID_CU:
00544                         id= MEM_callocN(sizeof(Curve), "curve");
00545                         break;
00546                 case ID_MB:
00547                         id= MEM_callocN(sizeof(MetaBall), "mball");
00548                         break;
00549                 case ID_MA:
00550                         id= MEM_callocN(sizeof(Material), "mat");
00551                         break;
00552                 case ID_TE:
00553                         id= MEM_callocN(sizeof(Tex), "tex");
00554                         break;
00555                 case ID_IM:
00556                         id= MEM_callocN(sizeof(Image), "image");
00557                         break;
00558                 case ID_LT:
00559                         id= MEM_callocN(sizeof(Lattice), "latt");
00560                         break;
00561                 case ID_LA:
00562                         id= MEM_callocN(sizeof(Lamp), "lamp");
00563                         break;
00564                 case ID_CA:
00565                         id= MEM_callocN(sizeof(Camera), "camera");
00566                         break;
00567                 case ID_IP:
00568                         id= MEM_callocN(sizeof(Ipo), "ipo");
00569                         break;
00570                 case ID_KE:
00571                         id= MEM_callocN(sizeof(Key), "key");
00572                         break;
00573                 case ID_WO:
00574                         id= MEM_callocN(sizeof(World), "world");
00575                         break;
00576                 case ID_SCR:
00577                         id= MEM_callocN(sizeof(bScreen), "screen");
00578                         break;
00579                 case ID_VF:
00580                         id= MEM_callocN(sizeof(VFont), "vfont");
00581                         break;
00582                 case ID_TXT:
00583                         id= MEM_callocN(sizeof(Text), "text");
00584                         break;
00585                 case ID_SCRIPT:
00586                         //XXX id= MEM_callocN(sizeof(Script), "script");
00587                         break;
00588                 case ID_SO:
00589                         id= MEM_callocN(sizeof(bSound), "sound");
00590                         break;
00591                 case ID_GR:
00592                         id= MEM_callocN(sizeof(Group), "group");
00593                         break;
00594                 case ID_AR:
00595                         id = MEM_callocN(sizeof(bArmature), "armature");
00596                         break;
00597                 case ID_AC:
00598                         id = MEM_callocN(sizeof(bAction), "action");
00599                         break;
00600                 case ID_NT:
00601                         id = MEM_callocN(sizeof(bNodeTree), "nodetree");
00602                         break;
00603                 case ID_BR:
00604                         id = MEM_callocN(sizeof(Brush), "brush");
00605                         break;
00606                 case ID_PA:
00607                         id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings");
00608                           break;
00609                 case ID_WM:
00610                         id = MEM_callocN(sizeof(wmWindowManager), "Window manager");
00611                           break;
00612                 case ID_GD:
00613                         id = MEM_callocN(sizeof(bGPdata), "Grease Pencil");
00614                         break;
00615         }
00616         return id;
00617 }
00618 
00619 /* used everywhere in blenkernel and text.c */
00620 void *alloc_libblock(ListBase *lb, short type, const char *name)
00621 {
00622         ID *id= NULL;
00623         
00624         id= alloc_libblock_notest(type);
00625         if(id) {
00626                 BLI_addtail(lb, id);
00627                 id->us= 1;
00628                 id->icon_id = 0;
00629                 *( (short *)id->name )= type;
00630                 new_id(lb, id, name);
00631                 /* alphabetic insterion: is in new_id */
00632         }
00633         return id;
00634 }
00635 
00636 /* by spec, animdata is first item after ID */
00637 /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */
00638 static void id_copy_animdata(ID *id, const short do_action)
00639 {
00640         AnimData *adt= BKE_animdata_from_id(id);
00641         
00642         if (adt) {
00643                 IdAdtTemplate *iat = (IdAdtTemplate *)id;
00644                 iat->adt= BKE_copy_animdata(iat->adt, do_action); /* could be set to FALSE, need to investigate */
00645         }
00646 }
00647 
00648 /* material nodes use this since they are not treated as libdata */
00649 void copy_libblock_data(ID *id, const ID *id_from, const short do_action)
00650 {
00651         if (id_from->properties)
00652                 id->properties = IDP_CopyProperty(id_from->properties);
00653 
00654         /* the duplicate should get a copy of the animdata */
00655         id_copy_animdata(id, do_action);
00656 }
00657 
00658 /* used everywhere in blenkernel */
00659 void *copy_libblock(void *rt)
00660 {
00661         ID *idn, *id;
00662         ListBase *lb;
00663         char *cp, *cpn;
00664         size_t idn_len;
00665         
00666         id= rt;
00667 
00668         lb= which_libbase(G.main, GS(id->name));
00669         idn= alloc_libblock(lb, GS(id->name), id->name+2);
00670 
00671         assert(idn != NULL);
00672 
00673         idn_len= MEM_allocN_len(idn);
00674         if(idn_len - sizeof(ID) > 0) {
00675                 cp= (char *)id;
00676                 cpn= (char *)idn;
00677                 memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID));
00678         }
00679         
00680         id->newid= idn;
00681         idn->flag |= LIB_NEW;
00682 
00683         copy_libblock_data(idn, id, FALSE);
00684         
00685         return idn;
00686 }
00687 
00688 static void free_library(Library *UNUSED(lib))
00689 {
00690         /* no freeing needed for libraries yet */
00691 }
00692 
00693 static void (*free_windowmanager_cb)(bContext *, wmWindowManager *)= NULL;
00694 
00695 void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) )
00696 {
00697         free_windowmanager_cb= func;
00698 }
00699 
00700 static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
00701 {
00702         ChannelDriver *driver;
00703         FCurve *fcu;
00704 
00705         /* find the driver this belongs to and update it */
00706         for (fcu=adt->drivers.first; fcu; fcu=fcu->next) {
00707                 driver= fcu->driver;
00708                 
00709                 if (driver) {
00710                         DriverVar *dvar;
00711                         for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
00712                                 DRIVER_TARGETS_USED_LOOPER(dvar) 
00713                                 {
00714                                         if (dtar->id == userdata)
00715                                                 dtar->id= NULL;
00716                                 }
00717                                 DRIVER_TARGETS_LOOPER_END
00718                         }
00719                 }
00720         }
00721 }
00722 
00723 
00724 /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */
00725 void free_libblock(ListBase *lb, void *idv)
00726 {
00727         ID *id= idv;
00728 
00729 #ifdef WITH_PYTHON
00730         BPY_id_release(id);
00731 #endif
00732 
00733         switch( GS(id->name) ) {        /* GetShort from util.h */
00734                 case ID_SCE:
00735                         free_scene((Scene *)id);
00736                         break;
00737                 case ID_LI:
00738                         free_library((Library *)id);
00739                         break;
00740                 case ID_OB:
00741                         free_object((Object *)id);
00742                         break;
00743                 case ID_ME:
00744                         free_mesh((Mesh *)id);
00745                         break;
00746                 case ID_CU:
00747                         free_curve((Curve *)id);
00748                         break;
00749                 case ID_MB:
00750                         free_mball((MetaBall *)id);
00751                         break;
00752                 case ID_MA:
00753                         free_material((Material *)id);
00754                         break;
00755                 case ID_TE:
00756                         free_texture((Tex *)id);
00757                         break;
00758                 case ID_IM:
00759                         free_image((Image *)id);
00760                         break;
00761                 case ID_LT:
00762                         free_lattice((Lattice *)id);
00763                         break;
00764                 case ID_LA:
00765                         free_lamp((Lamp *)id);
00766                         break;
00767                 case ID_CA:
00768                         free_camera((Camera*) id);
00769                         break;
00770                 case ID_IP:
00771                         free_ipo((Ipo *)id);
00772                         break;
00773                 case ID_KE:
00774                         free_key((Key *)id);
00775                         break;
00776                 case ID_WO:
00777                         free_world((World *)id);
00778                         break;
00779                 case ID_SCR:
00780                         free_screen((bScreen *)id);
00781                         break;
00782                 case ID_VF:
00783                         free_vfont((VFont *)id);
00784                         break;
00785                 case ID_TXT:
00786                         free_text((Text *)id);
00787                         break;
00788                 case ID_SCRIPT:
00789                         //XXX free_script((Script *)id);
00790                         break;
00791                 case ID_SO:
00792                         sound_free((bSound*)id);
00793                         break;
00794                 case ID_GR:
00795                         free_group_objects((Group *)id);
00796                         break;
00797                 case ID_AR:
00798                         free_armature((bArmature *)id);
00799                         break;
00800                 case ID_AC:
00801                         free_action((bAction *)id);
00802                         break;
00803                 case ID_NT:
00804                         ntreeFreeTree((bNodeTree *)id);
00805                         break;
00806                 case ID_BR:
00807                         free_brush((Brush *)id);
00808                         break;
00809                 case ID_PA:
00810                         psys_free_settings((ParticleSettings *)id);
00811                         break;
00812                 case ID_WM:
00813                         if(free_windowmanager_cb)
00814                                 free_windowmanager_cb(NULL, (wmWindowManager *)id);
00815                         break;
00816                 case ID_GD:
00817                         free_gpencil_data((bGPdata *)id);
00818                         break;
00819         }
00820 
00821         if (id->properties) {
00822                 IDP_FreeProperty(id->properties);
00823                 MEM_freeN(id->properties);
00824         }
00825 
00826         BLI_remlink(lb, id);
00827 
00828         /* this ID may be a driver target! */
00829         BKE_animdata_main_cb(G.main, animdata_dtar_clear_cb, (void *)id);
00830 
00831         MEM_freeN(id);
00832 }
00833 
00834 void free_libblock_us(ListBase *lb, void *idv)          /* test users */
00835 {
00836         ID *id= idv;
00837         
00838         id->us--;
00839 
00840         if(id->us<0) {
00841                 if(id->lib) printf("ERROR block %s %s users %d\n", id->lib->name, id->name, id->us);
00842                 else printf("ERROR block %s users %d\n", id->name, id->us);
00843         }
00844         if(id->us==0) {
00845                 if( GS(id->name)==ID_OB ) unlink_object((Object *)id);
00846                 
00847                 free_libblock(lb, id);
00848         }
00849 }
00850 
00851 
00852 void free_main(Main *mainvar)
00853 {
00854         /* also call when reading a file, erase all, etc */
00855         ListBase *lbarray[MAX_LIBARRAY];
00856         int a;
00857 
00858         a= set_listbasepointers(mainvar, lbarray);
00859         while(a--) {
00860                 ListBase *lb= lbarray[a];
00861                 ID *id;
00862                 
00863                 while ( (id= lb->first) ) {
00864                         free_libblock(lb, id);
00865                 }
00866         }
00867 
00868         MEM_freeN(mainvar);
00869 }
00870 
00871 /* ***************** ID ************************ */
00872 
00873 
00874 ID *find_id(const char *type, const char *name)         /* type: "OB" or "MA" etc */
00875 {
00876         ListBase *lb= which_libbase(G.main, GS(type));
00877         return BLI_findstring(lb, name, offsetof(ID, name) + 2);
00878 }
00879 
00880 static void get_flags_for_id(ID *id, char *buf) 
00881 {
00882         int isfake= id->flag & LIB_FAKEUSER;
00883         int isnode=0;
00884                 /* Writeout the flags for the entry, note there
00885                  * is a small hack that writes 5 spaces instead
00886                  * of 4 if no flags are displayed... this makes
00887                  * things usually line up ok - better would be
00888                  * to have that explicit, oh well - zr
00889                  */
00890 
00891         if(GS(id->name)==ID_MA)
00892                 isnode= ((Material *)id)->use_nodes;
00893         if(GS(id->name)==ID_TE)
00894                 isnode= ((Tex *)id)->use_nodes;
00895         
00896         if (id->us<0)
00897                 sprintf(buf, "-1W ");
00898         else if (!id->lib && !isfake && id->us && !isnode)
00899                 sprintf(buf, "     ");
00900         else if(isnode)
00901                 sprintf(buf, "%c%cN%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
00902         else
00903                 sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
00904 }
00905 
00906 #define IDPUP_NO_VIEWER 1
00907 
00908 static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int hideflag)
00909 {
00910         int i, nids= BLI_countlist(lb);
00911                 
00912         if (nr) *nr= -1;
00913         
00914         if (nr && nids>MAX_IDPUP) {
00915                 BLI_dynstr_append(pupds, "DataBrowse %x-2");
00916                 *nr= -2;
00917         } else {
00918                 ID *id;
00919                 
00920                 for (i=0, id= lb->first; id; id= id->next, i++) {
00921                         char buf[32];
00922                         
00923                         if (nr && id==link) *nr= i+1;
00924 
00925                         if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.')
00926                                 continue;
00927                         if (hideflag & IDPUP_NO_VIEWER)
00928                                 if (GS(id->name)==ID_IM)
00929                                         if ( ((Image *)id)->source==IMA_SRC_VIEWER )
00930                                                 continue;
00931                         
00932                         get_flags_for_id(id, buf);
00933                                 
00934                         BLI_dynstr_append(pupds, buf);
00935                         BLI_dynstr_append(pupds, id->name+2);
00936                         BLI_snprintf(buf, sizeof(buf), "%%x%d", i+1);
00937                         BLI_dynstr_append(pupds, buf);
00938                         
00939                         /* icon */
00940                         switch(GS(id->name))
00941                         {
00942                         case ID_MA: /* fall through */
00943                         case ID_TE: /* fall through */
00944                         case ID_IM: /* fall through */
00945                         case ID_WO: /* fall through */
00946                         case ID_LA: /* fall through */
00947                                 BLI_snprintf(buf, sizeof(buf), "%%i%d", BKE_icon_getid(id) );
00948                                 BLI_dynstr_append(pupds, buf);
00949                                 break;
00950                         default:
00951                                 break;
00952                         }
00953                         
00954                         if(id->next)
00955                                 BLI_dynstr_append(pupds, "|");
00956                 }
00957         }
00958 }
00959 
00960 
00961 /* used by headerbuttons.c buttons.c editobject.c editseq.c */
00962 /* if nr==NULL no MAX_IDPUP, this for non-header browsing */
00963 void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
00964 {
00965         DynStr *pupds= BLI_dynstr_new();
00966 
00967         if (title) {
00968                 BLI_dynstr_append(pupds, title);
00969                 BLI_dynstr_append(pupds, "%t|");
00970         }
00971         
00972         if (extraops) {
00973                 BLI_dynstr_append(pupds, extraops);
00974                 if (BLI_dynstr_get_len(pupds))
00975                         BLI_dynstr_append(pupds, "|");
00976         }
00977 
00978         IDnames_to_dyn_pupstring(pupds, lb, link, nr, 0);
00979         
00980         *str= BLI_dynstr_get_cstring(pupds);
00981         BLI_dynstr_free(pupds);
00982 }
00983 
00984 /* skips viewer images */
00985 void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
00986 {
00987         DynStr *pupds= BLI_dynstr_new();
00988         
00989         if (title) {
00990                 BLI_dynstr_append(pupds, title);
00991                 BLI_dynstr_append(pupds, "%t|");
00992         }
00993         
00994         if (extraops) {
00995                 BLI_dynstr_append(pupds, extraops);
00996                 if (BLI_dynstr_get_len(pupds))
00997                         BLI_dynstr_append(pupds, "|");
00998         }
00999         
01000         IDnames_to_dyn_pupstring(pupds, lb, link, nr, IDPUP_NO_VIEWER);
01001         
01002         *str= BLI_dynstr_get_cstring(pupds);
01003         BLI_dynstr_free(pupds);
01004 }
01005 
01006 static void sort_alpha_id(ListBase *lb, ID *id)
01007 {
01008         ID *idtest;
01009         
01010         /* insert alphabetically */
01011         if(lb->first!=lb->last) {
01012                 BLI_remlink(lb, id);
01013                 
01014                 idtest= lb->first;
01015                 while(idtest) {
01016                         if(BLI_strcasecmp(idtest->name, id->name)>0 || idtest->lib) {
01017                                 BLI_insertlinkbefore(lb, idtest, id);
01018                                 break;
01019                         }
01020                         idtest= idtest->next;
01021                 }
01022                 /* as last */
01023                 if(idtest==NULL) {
01024                         BLI_addtail(lb, id);
01025                 }
01026         }
01027         
01028 }
01029 
01030 /*
01031  * Check to see if there is an ID with the same name as 'name'.
01032  * Returns the ID if so, if not, returns NULL
01033  */
01034 static ID *is_dupid(ListBase *lb, ID *id, const char *name)
01035 {
01036         ID *idtest=NULL;
01037         
01038         for( idtest = lb->first; idtest; idtest = idtest->next ) {
01039                 /* if idtest is not a lib */ 
01040                 if( id != idtest && idtest->lib == NULL ) {
01041                         /* do not test alphabetic! */
01042                         /* optimized */
01043                         if( idtest->name[2] == name[0] ) {
01044                                 if(strcmp(name, idtest->name+2)==0) break;
01045                         }
01046                 }
01047         }
01048         
01049         return idtest;
01050 }
01051 
01052 /* 
01053  * Check to see if an ID name is already used, and find a new one if so.
01054  * Return 1 if created a new name (returned in name).
01055  *
01056  * Normally the ID that's being check is already in the ListBase, so ID *id
01057  * points at the new entry.  The Python Library module needs to know what
01058  * the name of a datablock will be before it is appended; in this case ID *id
01059  * id is NULL;
01060  */
01061 
01062 static int check_for_dupid(ListBase *lb, ID *id, char *name)
01063 {
01064         ID *idtest;
01065         int nr= 0, nrtest, a, left_len;
01066         char left[32], leftest[32], in_use[32];
01067 
01068         /* make sure input name is terminated properly */
01069         /* if( strlen(name) > 21 ) name[21]= 0; */
01070         /* removed since this is only ever called from one place - campbell */
01071 
01072         while (1) {
01073 
01074                 /* phase 1: id already exists? */
01075                 idtest = is_dupid(lb, id, name);
01076 
01077                 /* if there is no double, done */
01078                 if( idtest == NULL ) return 0;
01079 
01080                 /* we have a dup; need to make a new name */
01081                 /* quick check so we can reuse one of first 32 ids if vacant */
01082                 memset(in_use, 0, sizeof(in_use));
01083 
01084                 /* get name portion, number portion ("name.number") */
01085                 left_len= BLI_split_name_num(left, &nr, name, '.');
01086 
01087                 /* if new name will be too long, truncate it */
01088                 if(nr > 999 && left_len > 16) {
01089                         left[16]= 0;
01090                         left_len= 16;
01091                 }
01092                 else if(left_len > 17) {
01093                         left[17]= 0;
01094                         left_len= 17;
01095                 }
01096 
01097                 for(idtest= lb->first; idtest; idtest= idtest->next) {
01098                         if(             (id != idtest) &&
01099                                         (idtest->lib == NULL) &&
01100                                         (*name == *(idtest->name+2)) &&
01101                                         (strncmp(name, idtest->name+2, left_len)==0) &&
01102                                         (BLI_split_name_num(leftest, &nrtest, idtest->name+2, '.') == left_len)
01103                         ) {
01104                                 if(nrtest < sizeof(in_use))
01105                                         in_use[nrtest]= 1;      /* mark as used */
01106                                 if(nr <= nrtest)
01107                                         nr= nrtest+1;           /* track largest unused */
01108                         }
01109                 }
01110 
01111                 /* decide which value of nr to use */
01112                 for(a=0; a < sizeof(in_use); a++) {
01113                         if(a>=nr) break;        /* stop when we've check up to biggest */
01114                         if( in_use[a]==0 ) { /* found an unused value */
01115                                 nr = a;
01116                                 break;
01117                         }
01118                 }
01119 
01120                 /* If the original name has no numeric suffix, 
01121                  * rather than just chopping and adding numbers, 
01122                  * shave off the end chars until we have a unique name.
01123                  * Check the null terminators match as well so we dont get Cube.000 -> Cube.00 */
01124                 if (nr==0 && name[left_len]== '\0') {
01125                         int len = left_len-1;
01126                         idtest= is_dupid(lb, id, name);
01127                         
01128                         while (idtest && len> 1) {
01129                                 name[len--] = '\0';
01130                                 idtest= is_dupid(lb, id, name);
01131                         }
01132                         if (idtest == NULL) return 1;
01133                         /* otherwise just continue and use a number suffix */
01134                 }
01135                 
01136                 if(nr > 999 && left_len > 16) {
01137                         /* this would overflow name buffer */
01138                         left[16] = 0;
01139                         /* left_len = 16; */ /* for now this isnt used again */
01140                         memcpy(name, left, sizeof(char) * 17);
01141                         continue;
01142                 }
01143                 /* this format specifier is from hell... */
01144                 BLI_snprintf(name, sizeof(id->name) - 2,"%s.%.3d", left, nr);
01145 
01146                 return 1;
01147         }
01148 }
01149 
01150 /*
01151  * Only for local blocks: external en indirect blocks already have a
01152  * unique ID.
01153  *
01154  * return 1: created a new name
01155  */
01156 
01157 int new_id(ListBase *lb, ID *id, const char *tname)
01158 {
01159         int result;
01160         char name[MAX_ID_NAME-2];
01161 
01162         /* if library, don't rename */
01163         if(id->lib) return 0;
01164 
01165         /* if no libdata given, look up based on ID */
01166         if(lb==NULL) lb= which_libbase(G.main, GS(id->name));
01167 
01168         /* if no name given, use name of current ID
01169          * else make a copy (tname args can be const) */
01170         if(tname==NULL)
01171                 tname= id->name+2;
01172 
01173         strncpy(name, tname, sizeof(name)-1);
01174 
01175         /* if result > 21, strncpy don't put the final '\0' to name.
01176          * easier to assign each time then to check if its needed */
01177         name[sizeof(name)-1]= 0;
01178 
01179         if(name[0] == '\0') {
01180                 /* disallow empty names */
01181                 strcpy(name, ID_FALLBACK_NAME);
01182         }
01183         else {
01184                 /* disallow non utf8 chars,
01185                  * the interface checks for this but new ID's based on file names dont */
01186                 BLI_utf8_invalid_strip(name, strlen(name));
01187         }
01188 
01189         result = check_for_dupid(lb, id, name);
01190         strcpy(id->name+2, name);
01191 
01192         /* This was in 2.43 and previous releases
01193          * however all data in blender should be sorted, not just duplicate names
01194          * sorting should not hurt, but noting just incause it alters the way other
01195          * functions work, so sort every time */
01196         /* if( result )
01197                 sort_alpha_id(lb, id);*/
01198         
01199         sort_alpha_id(lb, id);
01200         
01201         return result;
01202 }
01203 
01204 /* next to indirect usage in read/writefile also in editobject.c scene.c */
01205 void clear_id_newpoins(void)
01206 {
01207         ListBase *lbarray[MAX_LIBARRAY];
01208         ID *id;
01209         int a;
01210 
01211         a= set_listbasepointers(G.main, lbarray);
01212         while(a--) {
01213                 id= lbarray[a]->first;
01214                 while(id) {
01215                         id->newid= NULL;
01216                         id->flag &= ~LIB_NEW;
01217                         id= id->next;
01218                 }
01219         }
01220 }
01221 
01222 /* only for library fixes */
01223 static void image_fix_relative_path(Image *ima)
01224 {
01225         if(ima->id.lib==NULL) return;
01226         if(strncmp(ima->name, "//", 2)==0) {
01227                 BLI_path_abs(ima->name, ima->id.lib->filepath);
01228                 BLI_path_rel(ima->name, G.main->name);
01229         }
01230 }
01231 
01232 #define LIBTAG(a)       if(a && a->id.lib) {a->id.flag &=~LIB_INDIRECT; a->id.flag |= LIB_EXTERN;}
01233 
01234 static void lib_indirect_test_id(ID *id, Library *lib)
01235 {
01236         
01237         if(id->lib) {
01238                 /* datablocks that were indirectly related are now direct links
01239                  * without this, appending data that has a link to other data will fail to write */
01240                 if(lib && id->lib->parent == lib) {
01241                         id_lib_extern(id);
01242                 }
01243                 return;
01244         }
01245         
01246         if(GS(id->name)==ID_OB) {               
01247                 Object *ob= (Object *)id;
01248                 bActionStrip *strip;
01249                 Mesh *me;
01250 
01251                 int a;
01252         
01253                 // XXX old animation system! --------------------------------------
01254                 for (strip=ob->nlastrips.first; strip; strip=strip->next){
01255                         LIBTAG(strip->object); 
01256                         LIBTAG(strip->act);
01257                         LIBTAG(strip->ipo);
01258                 }
01259                 // XXX: new animation system needs something like this?
01260         
01261                 for(a=0; a<ob->totcol; a++) {
01262                         LIBTAG(ob->mat[a]);
01263                 }
01264         
01265                 LIBTAG(ob->dup_group);
01266                 LIBTAG(ob->proxy);
01267                 
01268                 me= ob->data;
01269                 LIBTAG(me);
01270         }
01271 }
01272 
01273 void tag_main_lb(ListBase *lb, const short tag)
01274 {
01275         ID *id;
01276         if(tag) {
01277                 for(id= lb->first; id; id= id->next) {
01278                         id->flag |= LIB_DOIT;
01279                 }
01280         }
01281         else {
01282                 for(id= lb->first; id; id= id->next) {
01283                         id->flag &= ~LIB_DOIT;
01284                 }
01285         }
01286 }
01287 
01288 void tag_main_idcode(struct Main *mainvar, const short type, const short tag)
01289 {
01290         ListBase *lb= which_libbase(mainvar, type);
01291 
01292         tag_main_lb(lb, tag);
01293 }
01294 
01295 void tag_main(struct Main *mainvar, const short tag)
01296 {
01297         ListBase *lbarray[MAX_LIBARRAY];
01298         int a;
01299 
01300         a= set_listbasepointers(mainvar, lbarray);
01301         while(a--) {
01302                 tag_main_lb(lbarray[a], tag);
01303         }
01304 }
01305 
01306 /* if lib!=NULL, only all from lib local */
01307 void all_local(Library *lib, int untagged_only)
01308 {
01309         ListBase *lbarray[MAX_LIBARRAY], tempbase={NULL, NULL};
01310         ID *id, *idn;
01311         int a;
01312 
01313         a= set_listbasepointers(G.main, lbarray);
01314         while(a--) {
01315                 id= lbarray[a]->first;
01316                 
01317                 while(id) {
01318                         id->newid= NULL;
01319                         idn= id->next;          /* id is possibly being inserted again */
01320                         
01321                         /* The check on the second line (LIB_PRE_EXISTING) is done so its
01322                          * possible to tag data you dont want to be made local, used for
01323                          * appending data, so any libdata already linked wont become local
01324                          * (very nasty to discover all your links are lost after appending)  
01325                          * */
01326                         if(id->flag & (LIB_EXTERN|LIB_INDIRECT|LIB_NEW) &&
01327                           (untagged_only==0 || !(id->flag & LIB_PRE_EXISTING)))
01328                         {
01329                                 if(lib==NULL || id->lib==lib) {
01330                                         id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW);
01331 
01332                                         if(id->lib) {
01333                                                 /* relative file patch */
01334                                                 if(GS(id->name)==ID_IM)
01335                                                         image_fix_relative_path((Image *)id);
01336                                                 
01337                                                 id->lib= NULL;
01338                                                 new_id(lbarray[a], id, NULL);   /* new_id only does it with double names */
01339                                                 sort_alpha_id(lbarray[a], id);
01340                                         }
01341                                 }
01342                         }
01343                         id= idn;
01344                 }
01345                 
01346                 /* patch2: make it aphabetically */
01347                 while( (id=tempbase.first) ) {
01348                         BLI_remlink(&tempbase, id);
01349                         BLI_addtail(lbarray[a], id);
01350                         new_id(lbarray[a], id, NULL);
01351                 }
01352         }
01353 
01354         /* patch 3: make sure library data isn't indirect falsely... */
01355         a= set_listbasepointers(G.main, lbarray);
01356         while(a--) {
01357                 for(id= lbarray[a]->first; id; id=id->next)
01358                         lib_indirect_test_id(id, lib);
01359         }
01360 }
01361 
01362 
01363 void test_idbutton(char *name)
01364 {
01365         /* called from buttons: when name already exists: call new_id */
01366         ListBase *lb;
01367         ID *idtest;
01368         
01369 
01370         lb= which_libbase(G.main, GS(name-2) );
01371         if(lb==NULL) return;
01372         
01373         /* search for id */
01374         idtest= BLI_findstring(lb, name, offsetof(ID, name) + 2);
01375 
01376         if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest);
01377 }
01378 
01379 void text_idbutton(struct ID *id, char *text)
01380 {
01381         if(id) {
01382                 if(GS(id->name)==ID_SCE)
01383                         strcpy(text, "SCE: ");
01384                 else if(GS(id->name)==ID_SCR)
01385                         strcpy(text, "SCR: ");
01386                 else if(GS(id->name)==ID_MA && ((Material*)id)->use_nodes)
01387                         strcpy(text, "NT: ");
01388                 else {
01389                         text[0]= id->name[0];
01390                         text[1]= id->name[1];
01391                         text[2]= ':';
01392                         text[3]= ' ';
01393                         text[4]= 0;
01394                 }
01395         }
01396         else {
01397                 text[0]= '\0';
01398         }
01399 }
01400 
01401 void rename_id(ID *id, const char *name)
01402 {
01403         ListBase *lb;
01404 
01405         BLI_strncpy(id->name+2, name, sizeof(id->name)-2);
01406         lb= which_libbase(G.main, GS(id->name) );
01407         
01408         new_id(lb, id, name);                           
01409 }
01410 
01411 void name_uiprefix_id(char *name, ID *id)
01412 {
01413         name[0] = id->lib ? 'L':' ';
01414         name[1] = id->flag & LIB_FAKEUSER ? 'F': (id->us==0)?'0':' ';
01415         name[2] = ' ';
01416 
01417         strcpy(name+3, id->name+2);
01418 }