- got tired of str[n]casecmp not declared warnings
[blender.git] / source / blender / blenkernel / intern / library.c
1
2 /*  library.c 
3  * 
4  *  Contains management of ID's and libraries
5  *  allocate and free of all library data
6  * 
7  * $Id$
8  *
9  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version. The Blender
15  * Foundation also sells licenses for use in proprietary software under
16  * the Blender License.  See http://www.blender.org/BL/ for information
17  * about this.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  *
28  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
29  * All rights reserved.
30  *
31  * The Original Code is: all of this file.
32  *
33  * Contributor(s): none yet.
34  *
35  * ***** END GPL/BL DUAL LICENSE BLOCK *****
36  */
37 #include <stdio.h>
38 #include <ctype.h>
39 #include <string.h>
40 #include <stdlib.h>
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 #include "MEM_guardedalloc.h"
47
48 /* all types are needed here, in order to do memory operations */
49 #include "DNA_ID.h"
50 #include "DNA_listBase.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_lattice_types.h"
55 #include "DNA_curve_types.h"
56 #include "DNA_meta_types.h"
57 #include "DNA_material_types.h"
58 #include "DNA_texture_types.h"
59 #include "DNA_ika_types.h"
60 #include "DNA_image_types.h"
61 #include "DNA_wave_types.h"
62 #include "DNA_lamp_types.h"
63 #include "DNA_camera_types.h"
64 #include "DNA_ipo_types.h"
65 #include "DNA_key_types.h"
66 #include "DNA_world_types.h"
67 #include "DNA_screen_types.h"
68 #include "DNA_vfont_types.h"
69 #include "DNA_text_types.h"
70 #include "DNA_sound_types.h"
71 #include "DNA_group_types.h"
72 #include "DNA_armature_types.h"
73 #include "DNA_action_types.h"
74
75 #include "BLI_blenlib.h"
76 #include "BLI_dynstr.h"
77
78 #include "BKE_bad_level_calls.h"
79 #include "BKE_library.h"
80 #include "BKE_main.h"
81 #include "BKE_global.h"
82 #include "BKE_sound.h"
83 #include "BKE_object.h"
84 #include "BKE_screen.h"
85 #include "BKE_script.h"
86 #include "BKE_mesh.h"
87 #include "BKE_material.h"
88 #include "BKE_curve.h"
89 #include "BKE_mball.h"
90 #include "BKE_text.h"
91 #include "BKE_texture.h"
92 #include "BKE_scene.h"
93 #include "BKE_image.h"
94 #include "BKE_ika.h"
95 #include "BKE_ipo.h"
96 #include "BKE_key.h"
97 #include "BKE_world.h"
98 #include "BKE_font.h"
99 #include "BKE_group.h"
100 #include "BKE_lattice.h"
101 #include "BKE_armature.h"
102 #include "BKE_action.h"
103 #include "BPI_script.h"
104
105 #define MAX_IDPUP               30      /* was 24 */
106 #define MAX_LIBARRAY    100 /* was 30, warning: used it readfile.c too */
107
108 /* ************* general ************************ */
109
110 void id_lib_extern(ID *id)
111 {
112         if(id) {
113                 if(id->flag & LIB_INDIRECT) {
114                         id->flag -= LIB_INDIRECT;
115                         id->flag |= LIB_EXTERN;
116                 }
117         }
118 }
119
120 void id_us_plus(ID *id)
121 {
122         if(id) {
123                 id->us++;
124                 if(id->flag & LIB_INDIRECT) {
125                         id->flag -= LIB_INDIRECT;
126                         id->flag |= LIB_EXTERN;
127                 }
128         }
129 }
130
131 ListBase *wich_libbase(Main *mainlib, short type)
132 {
133         switch( type ) {
134                 case ID_SCE:
135                         return &(mainlib->scene);
136                 case ID_LI:
137                         return &(mainlib->library);
138                 case ID_OB:
139                         return &(mainlib->object);
140                 case ID_ME:
141                         return &(mainlib->mesh);
142                 case ID_CU:
143                         return &(mainlib->curve);
144                 case ID_MB:
145                         return &(mainlib->mball);
146                 case ID_MA:
147                         return &(mainlib->mat);
148                 case ID_TE:
149                         return &(mainlib->tex);
150                 case ID_IM:
151                         return &(mainlib->image);
152                 case ID_IK:
153                         return &(mainlib->ika);
154                 case ID_WV:
155                         return &(mainlib->wave);
156                 case ID_LT:
157                         return &(mainlib->latt);
158                 case ID_LA:
159                         return &(mainlib->lamp);
160                 case ID_CA:
161                         return &(mainlib->camera);
162                 case ID_IP:
163                         return &(mainlib->ipo);
164                 case ID_KE:
165                         return &(mainlib->key);
166                 case ID_WO:
167                         return &(mainlib->world);
168                 case ID_SCR:
169                         return &(mainlib->screen);
170                 case ID_VF:
171                         return &(mainlib->vfont);
172                 case ID_TXT:
173                         return &(mainlib->text);
174                 case ID_SCRIPT:
175                         return &(mainlib->script);
176                 case ID_SO:
177                         return &(mainlib->sound);
178                 case ID_SAMPLE:
179                         /* declared as an external in sound.h !!! */
180                         return (samples);
181                 case ID_GR:
182                         return &(mainlib->group);
183                 case ID_AR:
184                         return &(mainlib->armature);
185                 case ID_AC:
186                         return &(mainlib->action);
187         }
188         return 0;
189 }
190
191 int set_listbasepointers(Main *main, ListBase **lb)
192 {
193         /* BACKWARDS! also watch order of free-ing! (mesh<->mat) */
194
195         lb[0]= &(main->ipo);
196         lb[1]= &(main->key);
197         lb[2]= &(main->image);
198         lb[3]= &(main->tex);
199         lb[4]= &(main->mat);
200         lb[5]= &(main->vfont);
201         
202         /* Important!: When adding a new object type,
203          * the specific data should be inserted here 
204          */
205
206         lb[6]= &(main->armature);
207         lb[7]= &(main->action);
208
209         lb[8]= &(main->mesh);
210         lb[9]= &(main->curve);
211         lb[10]= &(main->mball);
212         lb[11]= &(main->ika);
213         lb[12]= &(main->wave);
214         lb[13]= &(main->latt);
215         lb[14]= &(main->lamp);
216         lb[15]= &(main->camera);
217
218         lb[16]= &(main->world);
219         lb[17]= &(main->screen);
220         lb[18]= &(main->object);
221         lb[19]= &(main->scene);
222         lb[20]= &(main->library);
223         lb[21]= &(main->text);
224         lb[22]= &(main->sound);
225         lb[23]= &(main->group);
226
227         lb[24]= samples;
228         lb[25]= &(main->script);
229         lb[26]=0;
230
231         return 26;
232 }
233
234 /* *********** ALLOC AND FREE *****************
235   
236 free_libblock(ListBase *lb, ID *id )
237         provide a list-basis and datablock, but only ID is read
238
239 void *alloc_libblock(ListBase *lb, type, name)
240         inserts in list and returns a new ID
241
242  ***************************** */
243
244 static ID *alloc_libblock_notest(short type)
245 {
246         ID *id= 0;
247         
248         switch( type ) {
249                 case ID_SCE:
250                         id= MEM_callocN(sizeof(Scene), "scene");
251                         break;
252                 case ID_LI:
253                         id= MEM_callocN(sizeof(Library), "library");
254                         break;
255                 case ID_OB:
256                         id= MEM_callocN(sizeof(Object), "object");
257                         break;
258                 case ID_ME:
259                         id= MEM_callocN(sizeof(Mesh), "mesh");
260                         break;
261                 case ID_CU:
262                         id= MEM_callocN(sizeof(Curve), "curve");
263                         break;
264                 case ID_MB:
265                         id= MEM_callocN(sizeof(MetaBall), "mball");
266                         break;
267                 case ID_MA:
268                         id= MEM_callocN(sizeof(Material), "mat");
269                         break;
270                 case ID_TE:
271                         id= MEM_callocN(sizeof(Tex), "tex");
272                         break;
273                 case ID_IM:
274                         id= MEM_callocN(sizeof(Image), "image");
275                         break;
276                 case ID_IK:
277                         id= MEM_callocN(sizeof(Ika), "ika");
278                         break;
279                 case ID_WV:
280                         id= MEM_callocN(sizeof(Wave), "wave");
281                         break;
282                 case ID_LT:
283                         id= MEM_callocN(sizeof(Lattice), "latt");
284                         break;
285                 case ID_LA:
286                         id= MEM_callocN(sizeof(Lamp), "lamp");
287                         break;
288                 case ID_CA:
289                         id= MEM_callocN(sizeof(Camera), "camera");
290                         break;
291                 case ID_IP:
292                         id= MEM_callocN(sizeof(Ipo), "ipo");
293                         break;
294                 case ID_KE:
295                         id= MEM_callocN(sizeof(Key), "key");
296                         break;
297                 case ID_WO:
298                         id= MEM_callocN(sizeof(World), "world");
299                         break;
300                 case ID_SCR:
301                         id= MEM_callocN(sizeof(bScreen), "screen");
302                         break;
303                 case ID_VF:
304                         id= MEM_callocN(sizeof(VFont), "vfont");
305                         break;
306                 case ID_TXT:
307                         id= MEM_callocN(sizeof(Text), "text");
308                         break;
309                 case ID_SCRIPT:
310                         id= MEM_callocN(sizeof(Script), "script");
311                         break;
312                 case ID_SO:
313                         id= MEM_callocN(sizeof(bSound), "sound");
314                         break;
315                 case ID_SAMPLE:
316                         id = MEM_callocN(sizeof(bSample), "sound");
317                         break;
318                 case ID_GR:
319                         id= MEM_callocN(sizeof(Group), "sound");
320                         break;
321                 case ID_AR:
322                         id = MEM_callocN(sizeof(bArmature), "armature");
323                         break;
324                 case ID_AC:
325                         id = MEM_callocN(sizeof(bAction), "action");
326                         break;
327         }
328         return id;
329 }
330
331 // used everywhere in blenkernel and text.c
332 void *alloc_libblock(ListBase *lb, short type, char *name)
333 {
334         ID *id= 0;
335         
336         id= alloc_libblock_notest(type);
337         if(id) {
338                 BLI_addtail(lb, id);
339                 id->us= 1;
340                 *( (short *)id->name )= type;
341                 new_id(lb, id, name);
342                 /* alphabetic insterion: is in new_id */
343         }
344         return id;
345 }
346
347 /* GS reads the memory pointed at in a specific ordering. There are,
348  * however two definitions for it. I have jotted them down here, both,
349  * but I think the first one is actually used. The thing is that
350  * big-endian systems might read this the wrong way round. OTOH, we
351  * constructed the IDs that are read out with this macro explicitly as
352  * well. I expect we'll sort it out soon... */
353
354 /* from blendef: */
355 #define GS(a)   (*((short *)(a)))
356
357 /* from misc_util: flip the bytes from x  */
358 /*#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
359
360 // used everywhere in blenkernel and text.c
361 void *copy_libblock(void *rt)
362 {
363         ID *idn, *id;
364         ListBase *lb;
365         char *cp, *cpn;
366         int idn_len;
367         
368         id= rt;
369
370         lb= wich_libbase(G.main, GS(id->name));
371         idn= alloc_libblock(lb, GS(id->name), id->name+2);
372         
373         idn_len= MEM_allocN_len(idn);
374         if(idn_len - sizeof(ID) > 0) {
375                 cp= (char *)id;
376                 cpn= (char *)idn;
377                 memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID));
378         }
379         
380         id->newid= idn;
381         idn->flag |= LIB_NEW;
382         
383         return idn;
384 }
385
386 static void free_library(Library *lib)
387 {
388     /* no freeing needed for libraries yet */
389 }
390
391 // used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
392 void free_libblock(ListBase *lb, void *idv)
393 {
394         ID *id= idv;
395         
396         switch( GS(id->name) ) {        /* GetShort from util.h */
397                 case ID_SCE:
398                         free_scene((Scene *)id);
399                         break;
400                 case ID_LI:
401                         free_library((Library *)id);
402                         break;
403                 case ID_OB:
404                         free_object((Object *)id);
405                         break;
406                 case ID_ME:
407                         free_mesh((Mesh *)id);
408                         break;
409                 case ID_CU:
410                         free_curve((Curve *)id);
411                         break;
412                 case ID_MB:
413                         free_mball((MetaBall *)id);
414                         break;
415                 case ID_MA:
416                         free_material((Material *)id);
417                         break;
418                 case ID_TE:
419                         free_texture((Tex *)id);
420                         break;
421                 case ID_IM:
422                         free_image((Image *)id);
423                         break;
424                 case ID_IK:
425                         free_ika((Ika *)id);
426                         break;
427                 case ID_WV:
428                         /* free_wave(id); */
429                         break;
430                 case ID_LT:
431                         free_lattice((Lattice *)id);
432                         break;
433                 case ID_LA:
434                         free_lamp((Lamp *)id);
435                         break;
436                 case ID_CA:
437                         free_camera((Camera*) id);
438                         break;
439                 case ID_IP:
440                         free_ipo((Ipo *)id);
441                         break;
442                 case ID_KE:
443                         free_key((Key *)id);
444                         break;
445                 case ID_WO:
446                         free_world((World *)id);
447                         break;
448                 case ID_SCR:
449                         free_screen((bScreen *)id);
450                         break;
451                 case ID_VF:
452                         free_vfont((VFont *)id);
453                         break;
454                 case ID_TXT:
455                         free_text((Text *)id);
456                         break;
457                 case ID_SCRIPT:
458                         free_script((Script *)id);
459                         break;
460                 case ID_SO:
461                         sound_free_sound((bSound *)id);
462                         break;
463                 case ID_SAMPLE:
464                         sound_free_sample((bSample *)id);
465                         break;
466                 case ID_GR:
467                         free_group((Group *)id);
468                         break;
469                 case ID_AR:
470                         free_armature((bArmature *)id);
471                         break;
472                 case ID_AC:
473                         free_action((bAction *)id);
474                         break;
475         }
476
477         BLI_remlink(lb, id);
478         MEM_freeN(id);
479
480         /* should not be here!! this is an interface-thing */
481         allspace(OOPS_TEST, 0);
482 }
483
484 void free_libblock_us(ListBase *lb, void *idv)          /* test users */
485 {
486         ID *id= idv;
487         
488         id->us--;
489
490         if(id->us<0) {
491                 if(id->lib) printf("ERROR block %s %s users %d\n", id->lib->name, id->name, id->us);
492                 else printf("ERROR block %s users %d\n", id->name, id->us);
493         }
494         if(id->us==0) {
495                 if( GS(id->name)==ID_OB ) unlink_object((Object *)id);
496                 
497                 free_libblock(lb, id);
498         }
499 }
500
501
502 void free_main(Main *mainvar)
503 {
504         /* also call when reading a file, erase all, etc */
505         ListBase *lbarray[MAX_LIBARRAY];
506         int a;
507
508         a= set_listbasepointers(mainvar, lbarray);
509         while(a--) {
510                 ListBase *lb= lbarray[a];
511                 ID *id;
512                 
513                 while ( (id= lb->first) ) {
514                         free_libblock(lb, id);
515                 }
516         }
517
518         MEM_freeN(mainvar);
519 }
520
521 /* ***************** ID ************************ */
522
523 // only used in exotic.c
524 ID *find_id(char *type, char *name)             /* type: "OB" or "MA" etc */
525 {
526         ID *id;
527         ListBase *lb;
528         
529         lb= wich_libbase(G.main, GS(type));
530         
531         id= lb->first;
532         while(id) {
533                 if( strcmp(id->name+2, name)==0 ) return id;
534                 id= id->next;
535         }
536         return 0;
537 }
538
539 static void get_flags_for_id(ID *id, char *buf) {
540         int isfake= id->flag & LIB_FAKEUSER;
541
542                 /* Writeout the flags for the entry, note there
543                  * is a small hack that writes 5 spaces instead
544                  * of 4 if no flags are displayed... this makes
545                  * things usually line up ok - better would be
546                  * to have that explicit, oh well - zr
547                  */
548
549         if (id->us<0)
550                 sprintf(buf, "-1W ");
551         else if (!id->lib && !isfake && id->us)
552                 sprintf(buf, "     ");
553         else
554                 sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
555 }
556
557 static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr)
558 {
559         int i, nids= BLI_countlist(lb);
560                 
561         if (nr) *nr= -1;
562         
563         if (nr && nids>MAX_IDPUP) {
564                 BLI_dynstr_append(pupds, "DataBrowse %x-2");
565         } else {
566                 ID *id;
567                 
568                 for (i=0, id= lb->first; id; id= id->next, i++) {
569                         char buf[32];
570                         
571                         if (nr && id==link) *nr= i+1;
572                         
573                         get_flags_for_id(id, buf);
574                                 
575                         BLI_dynstr_append(pupds, buf);
576                         BLI_dynstr_append(pupds, id->name+2);
577                         sprintf(buf, "%%x%d", i+1);
578                         BLI_dynstr_append(pupds, buf);
579                         
580                         if(id->next)
581                                 BLI_dynstr_append(pupds, "|");
582                 }
583         }
584 }
585
586         /* Silly routine, the only difference between the one
587          * above is that it only adds items with a matching
588          * blocktype... this should be unified somehow... - zr
589          */
590 static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype)
591 {
592         ID *id;
593         int i, nids;
594         
595         for (id= lb->first, nids= 0; id; id= id->next) {
596                 Ipo *ipo= (Ipo*) id;
597                 
598                 if (ipo->blocktype==blocktype)
599                         nids++;
600         }
601         
602         if (nids>MAX_IDPUP) {
603                 BLI_dynstr_append(pupds, "DataBrowse %x-2");
604         } else {
605                 for (i=0, id= lb->first; id; id= id->next) {
606                         Ipo *ipo= (Ipo*) id;
607                         
608                         if (ipo->blocktype==blocktype) {
609                                 char buf[32];
610                         
611                                 if (id==link)
612                                         *nr= i+1;
613                                         
614                                 get_flags_for_id(id, buf);
615                                 
616                                 BLI_dynstr_append(pupds, buf);
617                                 BLI_dynstr_append(pupds, id->name+2);
618                                 sprintf(buf, "%%x%d", i+1);
619                                 BLI_dynstr_append(pupds, buf);
620                                 
621                                 if(id->next)
622                                         BLI_dynstr_append(pupds, "|");
623                                 
624                                 i++;
625                         }
626                 }
627         }
628 }
629
630 // used by headerbuttons.c buttons.c editobject.c editseq.c
631 // if nr==NULL no MAX_IDPUP, this for non-header browsing
632 void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr)
633 {
634         DynStr *pupds= BLI_dynstr_new();
635
636         if (title) {
637                 BLI_dynstr_append(pupds, title);
638                 BLI_dynstr_append(pupds, "%t|");
639         }
640         
641         if (extraops) {
642                 BLI_dynstr_append(pupds, extraops);
643                 if (BLI_dynstr_get_len(pupds))
644                         BLI_dynstr_append(pupds, "|");
645         }
646
647         IDnames_to_dyn_pupstring(pupds, lb, link, nr);
648         
649         *str= BLI_dynstr_get_cstring(pupds);
650         BLI_dynstr_free(pupds);
651 }
652
653 // only used by headerbuttons.c
654 void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype)
655 {
656         DynStr *pupds= BLI_dynstr_new();
657         
658         if (title) {
659                 BLI_dynstr_append(pupds, title);
660                 BLI_dynstr_append(pupds, "%t|");
661         }
662         
663         if (extraops) {
664                 BLI_dynstr_append(pupds, extraops);
665                 if (BLI_dynstr_get_len(pupds))
666                         BLI_dynstr_append(pupds, "|");
667         }
668
669         IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype);      
670         
671         *str= BLI_dynstr_get_cstring(pupds);
672         BLI_dynstr_free(pupds);
673 }
674
675 // used by buttons.c library.c mball.c
676 void splitIDname(char *name, char *left, int *nr)
677 {
678         int a;
679         
680         *nr= 0;
681         strncpy(left, name, 21);
682         
683         a= strlen(name);
684         if(a>1 && name[a-1]=='.') return;
685         
686         while(a--) {
687                 if( name[a]=='.' ) {
688                         left[a]= 0;
689                         *nr= atol(name+a+1);
690                         return;
691                 }
692                 if( isdigit(name[a])==0 ) break;
693                 
694                 left[a]= 0;
695         }
696         strcpy(left, name);     
697 }
698
699 static void sort_alpha_id(ListBase *lb, ID *id)
700 {
701         ID *idtest;
702         
703         /* insert alphabetically */
704         if(lb->first!=lb->last) {
705                 BLI_remlink(lb, id);
706                 
707                 idtest= lb->first;
708                 while(idtest) {
709                         if(BLI_strcasecmp(idtest->name, id->name)>0 || idtest->lib) {
710                                 BLI_insertlinkbefore(lb, idtest, id);
711                                 break;
712                         }
713                         idtest= idtest->next;
714                 }
715                 /* as last */
716                 if(idtest==0) {
717                         BLI_addtail(lb, id);
718                 }
719         }
720         
721 }
722
723 int new_id(ListBase *lb, ID *id, char *tname)
724 /* only for local blocks: external en indirect blocks already have a unique ID */
725 /* return 1: created a new name */
726 {
727         ID *idtest;
728         int nr= 0, nrtest, maxtest=32, a;
729         char aname[32], *name, left[24], leftest[24], in_use[32];
730         
731         /* - split name
732          * - search
733          */
734
735         if(id->lib) return 0;
736
737         if(tname==0) name= id->name+2;
738         else {
739                 /* tname can be const */
740                 strncpy(aname, tname, 21);
741                 name= aname;
742                 
743                 if( strlen(name) > 21 ) name[21]= 0;
744         }
745
746         if(lb==0) lb= wich_libbase(G.main, GS(id->name));
747
748         /* phase 1: id already exists? */
749         idtest= lb->first;
750         while(idtest) {
751         
752                 if(id!=idtest && idtest->lib==0) {
753                         
754                         /* do not test alphabetic! */
755                         /* optimized */
756                         if( idtest->name[2] == name[0] ) {
757                                 if(strcmp(name, idtest->name+2)==0) break;
758                         }
759                 }
760                 
761                 idtest= idtest->next;
762         }       
763
764         /* if there is no double return */
765         if(idtest==0) {
766                 strcpy(id->name+2, name);
767                 return 0;
768         }
769         
770         memset(in_use, 0, maxtest);
771
772         splitIDname(name, left, &nr);
773         if(nr>999 && strlen(left)>16) left[16]= 0;
774         else if(strlen(left)>17) left[17]= 0;
775
776
777         idtest= lb->first;
778         while(idtest) {
779         
780                 if(id!=idtest && idtest->lib==0) {
781                         
782                         splitIDname(idtest->name+2, leftest, &nrtest);
783                         if(strcmp(left, leftest)==0) {
784                                 
785                                 if(nrtest<maxtest) in_use[nrtest]= 1;
786                                 if(nr <= nrtest) nr= nrtest+1;
787                         }
788                 }
789                 
790                 idtest= idtest->next;
791         }
792         
793         for(a=0; a<maxtest; a++) {
794                 if(a>=nr) break;
795                 if( in_use[a]==0 ) {
796                         nr= a;
797                         break;
798                 }
799         }
800         
801         if(nr==0) sprintf(id->name+2, "%s", left);
802         else {
803                 if (nr >= 1000 && strlen(left) > 16) {
804                         // this would overflow name buffer
805                         left[16]= 0;
806                         return (new_id(lb, id, left));
807                 }
808                 /* this format specifier is from hell... */
809                 sprintf(id->name+2, "%s.%.3d", left, nr);
810         }
811         
812         sort_alpha_id(lb, id);  
813
814         return 1;
815 }
816
817 // next to indirect usage in read/writefile also in editobject.c scene.c
818 void clear_id_newpoins()
819 {
820         ListBase *lbarray[MAX_LIBARRAY];
821         ID *id;
822         int a;
823
824         a= set_listbasepointers(G.main, lbarray);
825         while(a--) {
826                 id= lbarray[a]->first;
827                 while(id) {
828                         id->newid= 0;
829                         id->flag &= ~LIB_NEW;
830                         id= id->next;
831                 }
832         }
833 }
834
835 /* if lib!=NULL, only all from lib local */
836 void all_local(Library *lib)
837 {
838         ListBase *lbarray[MAX_LIBARRAY], tempbase={0, 0};
839         ID *id, *idn;
840         int a;
841
842         a= set_listbasepointers(G.main, lbarray);
843         while(a--) {
844                 id= lbarray[a]->first;
845                 
846                 while(id) {
847                         id->newid= NULL;
848                         idn= id->next;          /* id is possibly being inserted again */
849                         
850                         if(id->flag & (LIB_EXTERN|LIB_INDIRECT|LIB_NEW)) {
851                                 if(lib==NULL || id->lib==lib) {
852                                         id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW);
853
854                                         if(id->lib) {
855                                                 id->lib= NULL;
856                                                 new_id(lbarray[a], id, 0);      /* new_id only does it with double names */
857                                                 sort_alpha_id(lbarray[a], id);
858                                         }
859                                 }
860                         }
861                         id= idn;
862                 }
863                 
864                 /* patch2: make it aphabetically */
865                 while( (id=tempbase.first) ) {
866                         BLI_remlink(&tempbase, id);
867                         BLI_addtail(lbarray[a], id);
868                         new_id(lbarray[a], id, 0);
869                 }
870         }
871 }
872
873
874 void test_idbutton(char *name)
875 {
876         /* called from buttons: when name already exists: call new_id */
877         ListBase *lb;
878         ID *idtest;
879         
880
881         lb= wich_libbase(G.main, GS(name-2) );
882         if(lb==0) return;
883         
884         /* search for id */
885         idtest= lb->first;
886         while(idtest) {
887                 if( strcmp(idtest->name+2, name)==0) break;
888                 idtest= idtest->next;
889         }
890
891         if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest);
892 }
893
894 void rename_id(ID *id, char *name)
895 {
896         ListBase *lb;
897         
898         strncpy(id->name+2, name, 21);
899         lb= wich_libbase(G.main, GS(id->name) );
900         
901         new_id(lb, id, name);                           
902 }
903