Merged changes in the trunk up to revision 41225.
[blender.git] / source / blender / blenlib / intern / bpath.c
1 /*
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): Campbell barton
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/blenlib/intern/bpath.c
30  *  \ingroup bli
31  */
32
33
34 #include <sys/stat.h>
35
36 #include <string.h>
37 #include <assert.h>
38
39 /* path/file handeling stuff */
40 #ifndef WIN32
41   #include <dirent.h>
42   #include <unistd.h>
43 #else
44   #include <io.h>
45   #include "BLI_winstuff.h"
46 #endif
47
48 #include "MEM_guardedalloc.h"
49
50 #include "DNA_mesh_types.h"
51 #include "DNA_scene_types.h" /* to get the current frame */
52 #include "DNA_image_types.h"
53 #include "DNA_texture_types.h"
54 #include "DNA_text_types.h"
55 #include "DNA_sound_types.h"
56 #include "DNA_sequence_types.h"
57 #include "DNA_vfont_types.h"
58 #include "DNA_windowmanager_types.h"
59 #include "DNA_freestyle_types.h"
60
61 #include "BLI_blenlib.h"
62 #include "BLI_bpath.h"
63 #include "BLI_utildefines.h"
64
65 #include "BKE_global.h"
66 #include "BKE_image.h" /* so we can check the image's type */
67 #include "BKE_sequencer.h"
68 #include "BKE_main.h"
69 #include "BKE_utildefines.h"
70 #include "BKE_report.h"
71
72 typedef struct BPathIteratorSeqData
73 {
74         int totseq;
75         int seq;
76         struct Sequence **seqar; /* Sequence */
77         struct Scene *scene;                    /* Current scene */
78 } BPathIteratorSeqData;
79
80 typedef struct BPathIteratorFrsModuleData {
81         struct Scene *scene;                    /* Current scene */
82         struct SceneRenderLayer *layer; /* Scene render layer */
83         struct FreestyleModuleConfig *module;
84 } BPathIteratorFrsModuleData;
85
86 typedef struct BPathIterator
87 {
88         char*   _path; /* never access directly, use BLI_bpathIterator_getPath */
89         const char*     _lib;
90         const char*     _name;
91         void*   data;
92         int             len;
93         int             type;
94         int             flag; /* iterator options */
95
96         void (*setpath_callback)(struct BPathIterator *, const char *);
97         void (*getpath_callback)(struct BPathIterator *, char *);
98
99         const char*     base_path; /* base path, the directory the blend file is in - normally bmain->name */
100
101         Main *bmain;
102
103         /* only for seq data */
104         struct BPathIteratorSeqData seqdata;
105         /* only for Freestyle module data */
106         struct BPathIteratorFrsModuleData frsmoduledata;
107 } BPathIterator;
108
109 #define FILE_MAX                        240
110
111
112 /* TODO - BPATH_PLUGIN, BPATH_SEQ */
113 enum BPathTypes {
114         BPATH_IMAGE= 0,
115         BPATH_TEXTURE,
116         BPATH_TEXT,
117         BPATH_SOUND,
118         BPATH_FONT,
119         BPATH_LIB,
120         BPATH_SEQ,
121         BPATH_CDATA,
122         BPATH_FRS_MODULE,
123
124          BPATH_DONE
125 };
126
127 void BLI_bpathIterator_init(struct BPathIterator **bpi_pt, Main *bmain, const char *basedir, const int flag)
128 {
129         BPathIterator *bpi;
130
131         bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_init");
132         *bpi_pt= bpi;
133
134         bpi->type= BPATH_IMAGE;
135         bpi->data= NULL;
136         
137         bpi->getpath_callback= NULL;
138         bpi->setpath_callback= NULL;
139         
140         /* Sequencer specific */
141         bpi->seqdata.totseq= 0;
142         bpi->seqdata.seq= 0;
143         bpi->seqdata.seqar= NULL;
144         bpi->seqdata.scene= NULL;
145
146         bpi->flag= flag;
147
148         /* Freestyle module specific */
149         bpi->frsmoduledata.scene= NULL;
150         bpi->frsmoduledata.layer= NULL;
151         bpi->frsmoduledata.module= NULL;
152
153         bpi->base_path= basedir; /* normally bmain->name */
154         bpi->bmain= bmain;
155
156         BLI_bpathIterator_step(bpi);
157 }
158
159 #if 0
160 static void BLI_bpathIterator_alloc(struct BPathIterator **bpi)
161 {
162         *bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_alloc");
163 }
164 #endif
165
166 void BLI_bpathIterator_free(struct BPathIterator *bpi)
167 {
168         if (bpi->seqdata.seqar)
169                 MEM_freeN((void *)bpi->seqdata.seqar);
170         bpi->seqdata.seqar= NULL;
171         bpi->seqdata.scene= NULL;
172         bpi->frsmoduledata.scene= NULL;
173         bpi->frsmoduledata.layer= NULL;
174         bpi->frsmoduledata.module= NULL;
175         
176         MEM_freeN(bpi);
177 }
178
179 void BLI_bpathIterator_getPath(struct BPathIterator *bpi, char *path)
180 {
181         if (bpi->getpath_callback) {
182                 bpi->getpath_callback( bpi, path );
183         }
184         else {
185                 strcpy(path, bpi->_path); /* warning, we assume 'path' are long enough */
186         }
187 }
188
189 void BLI_bpathIterator_setPath(struct BPathIterator *bpi, const char *path)
190 {
191         if (bpi->setpath_callback) {
192                 bpi->setpath_callback( bpi, path );
193         }
194         else {
195                 strcpy(bpi->_path, path); /* warning, we assume 'path' are long enough */
196         }
197 }
198
199 void BLI_bpathIterator_getPathExpanded(struct BPathIterator *bpi, char *path_expanded)
200 {
201         const char *libpath;
202         
203         BLI_bpathIterator_getPath(bpi, path_expanded);
204         libpath= BLI_bpathIterator_getLib(bpi);
205         
206         if (libpath) { /* check the files location relative to its library path */
207                 BLI_path_abs(path_expanded, libpath);
208         }
209         else { /* local data, use the blend files path */
210                 BLI_path_abs(path_expanded, bpi->base_path);
211         }
212         BLI_cleanup_file(NULL, path_expanded);
213 }
214 const char* BLI_bpathIterator_getLib(struct BPathIterator *bpi)
215 {
216         return bpi->_lib;
217 }
218 const char* BLI_bpathIterator_getName(struct BPathIterator *bpi)
219 {
220         return bpi->_name;
221 }
222 int     BLI_bpathIterator_getType(struct BPathIterator *bpi)
223 {
224         return bpi->type;
225 }
226 unsigned int    BLI_bpathIterator_getPathMaxLen(struct BPathIterator *bpi)
227 {
228         return bpi->len;
229 }
230 const char* BLI_bpathIterator_getBasePath(struct BPathIterator *bpi)
231 {
232         return bpi->base_path;
233 }
234
235 /* gets the first or the next image that has a path - not a viewer node or generated image */
236 static struct Image *ima_stepdata__internal(struct Image *ima, const int step_next, const int flag)
237 {
238         if (ima==NULL)
239                 return NULL;
240         
241         if (step_next)
242                 ima= ima->id.next;
243         
244         while (ima) {
245                 if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
246                         if(ima->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
247                                 break;
248                         }
249                 }
250                 /* image is not a image with a path, skip it */
251                 ima= ima->id.next;
252         }       
253         return ima;
254 }
255
256 static struct Tex *tex_stepdata__internal(struct Tex *tex, const int step_next, const int UNUSED(flag))
257 {
258         if (tex==NULL)
259                 return NULL;
260
261         if (step_next)
262                 tex= tex->id.next;
263
264         while (tex) {
265                 if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format))
266                         break;
267                 /* image is not a image with a path, skip it */
268                 tex= tex->id.next;
269         }       
270         return tex;
271 }
272
273 static struct Text *text_stepdata__internal(struct Text *text, const int step_next, const int UNUSED(flag))
274 {
275         if (text==NULL)
276                 return NULL;
277
278         if (step_next)
279                 text= text->id.next;
280
281         while (text) {
282                 if (text->name)
283                         break;
284                 /* image is not a image with a path, skip it */
285                 text= text->id.next;
286         }       
287         return text;
288 }
289
290 static struct VFont *vf_stepdata__internal(struct VFont *vf, const int step_next, const int flag)
291 {
292         if (vf==NULL)
293                 return NULL;
294         
295         if (step_next)
296                 vf= vf->id.next;
297         
298         while (vf) {
299                 if (strcmp(vf->name, FO_BUILTIN_NAME)!=0) {
300                         if(vf->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
301                                 break;
302                         }
303                 }
304                 
305                 /* font with no path, skip it */
306                 vf= vf->id.next;
307         }       
308         return vf;
309 }
310
311 static struct bSound *snd_stepdata__internal(struct bSound *snd, int step_next, const int flag)
312 {
313         if (snd==NULL)
314                 return NULL;
315         
316         if (step_next)
317                 snd= snd->id.next;
318         
319         while (snd) {
320                 if(snd->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
321                         break;
322                 }
323
324                 /* font with no path, skip it */
325                 snd= snd->id.next;
326         }       
327         return snd;
328 }
329
330 static struct Sequence *seq_stepdata__internal(struct BPathIterator *bpi, int step_next)
331 {
332         Editing *ed;
333         Sequence *seq;
334         
335         /* Initializing */
336         if (bpi->seqdata.scene==NULL) {
337                 bpi->seqdata.scene= bpi->bmain->scene.first;
338         }
339         
340         if (step_next) {
341                 bpi->seqdata.seq++;
342         }
343         
344         while (bpi->seqdata.scene) {
345                 ed= seq_give_editing(bpi->seqdata.scene, 0);
346                 if (ed) {
347                         if (bpi->seqdata.seqar == NULL) {
348                                 /* allocate the sequencer array */
349                                 seq_array(ed, &bpi->seqdata.seqar, &bpi->seqdata.totseq, 0);
350                                 bpi->seqdata.seq= 0;
351                         }
352                         
353                         if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
354                                 seq= NULL;
355                         }
356                         else {
357                                 seq= bpi->seqdata.seqar[bpi->seqdata.seq];
358                                 while (!SEQ_HAS_PATH(seq) && seq->plugin==NULL) {
359                                         bpi->seqdata.seq++;
360                                         if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
361                                                 seq= NULL;
362                                                 break;
363                                         }
364                                         seq= bpi->seqdata.seqar[bpi->seqdata.seq];
365                                 }
366                         }
367                         if (seq) {
368                                 return seq;
369                         }
370                         else {
371                                 /* keep looking through the next scene, reallocate seq array */
372                                 if (bpi->seqdata.seqar) {
373                                         MEM_freeN((void *)bpi->seqdata.seqar);
374                                         bpi->seqdata.seqar= NULL;
375                                 }
376                                 bpi->seqdata.scene= bpi->seqdata.scene->id.next;
377                         }
378                 }
379                 else {
380                         /* no seq data in this scene, next */
381                         bpi->seqdata.scene= bpi->seqdata.scene->id.next;
382                 }
383         }
384         
385         return NULL;
386 }
387
388 static struct FreestyleModuleConfig *frs_module_stepdata__internal(struct BPathIterator *bpi, int step_next)
389 {
390         struct FreestyleModuleConfig *module;
391
392         /* Initializing */
393         if (bpi->frsmoduledata.scene==NULL) {
394                 bpi->frsmoduledata.scene= G.main->scene.first;
395                 bpi->frsmoduledata.layer= (bpi->frsmoduledata.scene) ? bpi->frsmoduledata.scene->r.layers.first : NULL;
396                 bpi->frsmoduledata.module= (bpi->frsmoduledata.layer) ? bpi->frsmoduledata.layer->freestyleConfig.modules.first : NULL;
397         }
398
399         while (bpi->frsmoduledata.scene) {
400                 while (bpi->frsmoduledata.layer) {
401                         while (bpi->frsmoduledata.module) {
402                                 module= bpi->frsmoduledata.module;
403                                 bpi->frsmoduledata.module= module->next;
404                                 return module;
405                         }
406                         bpi->frsmoduledata.layer= bpi->frsmoduledata.layer->next;
407                         bpi->frsmoduledata.module= (bpi->frsmoduledata.layer) ? bpi->frsmoduledata.layer->freestyleConfig.modules.first : NULL;
408                 }
409                 bpi->frsmoduledata.scene= bpi->frsmoduledata.scene->id.next;
410                 bpi->frsmoduledata.layer= (bpi->frsmoduledata.scene) ? bpi->frsmoduledata.scene->r.layers.first : NULL;
411                 bpi->frsmoduledata.module= (bpi->frsmoduledata.layer) ? bpi->frsmoduledata.layer->freestyleConfig.modules.first : NULL;
412         }
413
414         return NULL;
415 }
416
417 static void seq_getpath(struct BPathIterator *bpi, char *path)
418 {
419         Sequence *seq= (Sequence *)bpi->data;
420
421         
422         path[0]= '\0'; /* incase we cant get the path */
423         if (seq==NULL) return;
424         if (SEQ_HAS_PATH(seq)) {
425                 if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
426                         BLI_strncpy(path, seq->strip->dir, FILE_MAX);
427                         BLI_add_slash(path); /* incase its missing */
428                         if (seq->strip->stripdata) { /* should always be true! */
429                                 /* Using the first image is weak for image sequences */
430                                 strcat(path, seq->strip->stripdata->name);
431                         } 
432                 }
433                 else {
434                         /* simple case */
435                         BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
436                 }
437         }
438         else if (seq->plugin) {
439                 BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name));
440         }
441 }
442
443 static void seq_setpath(struct BPathIterator *bpi, const char *path)
444 {
445         Sequence *seq= (Sequence *)bpi->data;
446         if (seq==NULL) return; 
447         
448         if (SEQ_HAS_PATH(seq)) {
449                 if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
450                         BLI_split_dirfile(path, seq->strip->dir, seq->strip->stripdata->name, sizeof(seq->strip->dir), sizeof(seq->strip->stripdata->name));
451                 }
452                 else {
453                         /* simple case */
454                         BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
455                 }
456         }
457         else if (seq->plugin) {
458                 BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name));
459         }
460 }
461
462 static void text_getpath(struct BPathIterator *bpi, char *path)
463 {
464         Text *text= (Text *)bpi->data;
465         path[0]= '\0'; /* incase we cant get the path */
466         if(text->name) {
467                 strcpy(path, text->name);
468         }
469 }
470
471 static void text_setpath(struct BPathIterator *bpi, const char *path)
472 {
473         Text *text= (Text *)bpi->data;
474         if (text==NULL) return; 
475
476         if(text->name) {
477                 MEM_freeN(text->name);
478         }
479
480         text->name= BLI_strdup(path);
481 }
482
483 static struct Mesh *cdata_stepdata__internal(struct Mesh *me, int step_next)
484 {
485         if (me==NULL)
486                 return NULL;
487         
488         if (step_next)
489                 me= me->id.next;
490         
491         while (me) {
492                 if (me->fdata.external) {
493                         break;
494                 }
495                 
496                 me= me->id.next;
497         }       
498         return me;
499 }
500
501 static void bpi_type_step__internal(struct BPathIterator *bpi)
502 {
503         bpi->type++; /* advance to the next type */
504         bpi->data= NULL;
505         
506         switch (bpi->type) {
507         case BPATH_SEQ:
508                 bpi->getpath_callback= seq_getpath;
509                 bpi->setpath_callback= seq_setpath;
510                 break;
511         case BPATH_TEXT: /* path is malloc'd */
512                 bpi->getpath_callback= text_getpath;
513                 bpi->setpath_callback= text_setpath;
514                 break;
515         default:
516                 bpi->getpath_callback= NULL;
517                 bpi->setpath_callback= NULL;
518                 break;
519         }
520 }
521
522 void BLI_bpathIterator_step(struct BPathIterator *bpi)
523 {
524         while (bpi->type != BPATH_DONE) {
525                 
526                 if  ((bpi->type) == BPATH_IMAGE) {
527                         /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
528                         if (bpi->data)  bpi->data= ima_stepdata__internal((Image *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
529                         else                    bpi->data= ima_stepdata__internal(bpi->bmain->image.first, 0, bpi->flag);
530                         
531                         if (bpi->data) {
532                                 /* get the path info from this datatype */
533                                 Image *ima= (Image *)bpi->data;
534                                 
535                                 bpi->_lib= ima->id.lib ? ima->id.lib->filepath : NULL;
536                                 bpi->_path= ima->name;
537                                 bpi->_name= ima->id.name+2;
538                                 bpi->len= sizeof(ima->name);
539                                 
540                                 /* we are done, advancing to the next item, this type worked fine */
541                                 break;
542
543                         }
544                         else {
545                                 bpi_type_step__internal(bpi);
546                         }
547                 }
548
549                 if  ((bpi->type) == BPATH_TEXTURE) {
550                         /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
551                         if (bpi->data)  bpi->data= tex_stepdata__internal( (Tex *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
552                         else                    bpi->data= tex_stepdata__internal(bpi->bmain->tex.first, 0, bpi->flag);
553
554                         if (bpi->data) {
555                                 /* get the path info from this datatype */
556                                 Tex *tex= (Tex *)bpi->data;
557
558                                 if(tex->type == TEX_VOXELDATA) {
559                                         bpi->_lib= tex->id.lib ? tex->id.lib->filepath : NULL;
560                                         bpi->_path= tex->vd->source_path;
561                                         bpi->_name= tex->id.name+2;
562                                         bpi->len= sizeof(tex->vd->source_path);
563                                 }
564                                 else {
565                                         assert(!"Texture has no path, incorrect step 'tex_stepdata__internal'");
566                                 }
567
568                                 /* we are done, advancing to the next item, this type worked fine */
569                                 break;
570
571                         }
572                         else {
573                                 bpi_type_step__internal(bpi);
574                         }
575                 }
576
577                 if  ((bpi->type) == BPATH_TEXT) {
578                         /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
579                         if (bpi->data)  bpi->data= text_stepdata__internal((Text *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
580                         else                    bpi->data= text_stepdata__internal(bpi->bmain->text.first, 0, bpi->flag);
581
582                         if (bpi->data) {
583                                 /* get the path info from this datatype */
584                                 Text *text= (Text *)bpi->data;
585
586                                 bpi->_lib= text->id.lib ? text->id.lib->filepath : NULL;
587                                 bpi->_path= NULL; /* bpi->path= text->name; */ /* get/set functions override. */
588                                 bpi->_name= text->id.name+2;
589                                 bpi->len= FILE_MAX; /* malloc'd but limit anyway since large paths may mess up other areas */
590
591                                 /* we are done, advancing to the next item, this type worked fine */
592                                 break;
593
594                         }
595                         else {
596                                 bpi_type_step__internal(bpi);
597                         }
598                 }
599                 else if  ((bpi->type) == BPATH_SOUND) {
600                         if (bpi->data)  bpi->data= snd_stepdata__internal((bSound *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
601                         else                    bpi->data= snd_stepdata__internal(bpi->bmain->sound.first, 0, bpi->flag);
602
603                         if (bpi->data) {
604                                 /* get the path info from this datatype */
605                                 bSound *snd= (bSound *)bpi->data;
606
607                                 bpi->_lib= snd->id.lib ? snd->id.lib->filepath : NULL;
608                                 bpi->_path= snd->name;
609                                 bpi->_name= snd->id.name+2;
610                                 bpi->len= sizeof(snd->name);
611
612                                 /* we are done, advancing to the next item, this type worked fine */
613                                 break;
614                         }
615                         else {
616                                 bpi_type_step__internal(bpi);
617                         }
618                 }
619                 else if  ((bpi->type) == BPATH_FONT) {
620                         
621                         if (bpi->data)  bpi->data= vf_stepdata__internal((VFont *)bpi->data, 1, bpi->flag);
622                         else                    bpi->data= vf_stepdata__internal(bpi->bmain->vfont.first, 0, bpi->flag);
623                         
624                         if (bpi->data) {
625                                 /* get the path info from this datatype */
626                                 VFont *vf= (VFont *)bpi->data;
627
628                                 bpi->_lib= vf->id.lib ? vf->id.lib->filepath : NULL;
629                                 bpi->_path= vf->name;
630                                 bpi->_name= vf->id.name+2;
631                                 bpi->len= sizeof(vf->name);
632
633                                 /* we are done, advancing to the next item, this type worked fine */
634                                 break;
635                         }
636                         else {
637                                 bpi_type_step__internal(bpi);
638                         }
639
640                 }
641                 else if  ((bpi->type) == BPATH_LIB) {
642                         if (bpi->data)  bpi->data= ((ID *)bpi->data)->next;
643                         else                    bpi->data= bpi->bmain->library.first;
644                         
645                         if (bpi->data) {
646                                 /* get the path info from this datatype */
647                                 Library *lib= (Library *)bpi->data;
648                                 
649                                 bpi->_lib= NULL;
650                                 bpi->_path= lib->name;
651                                 bpi->_name= NULL;
652                                 bpi->len= sizeof(lib->name);
653                                 
654                                 /* we are done, advancing to the next item, this type worked fine */
655                                 break;
656                         }
657                         else {
658                                 bpi_type_step__internal(bpi);
659                         }
660                 }
661                 else if  ((bpi->type) == BPATH_SEQ) {
662                         if (bpi->data)  bpi->data= seq_stepdata__internal( bpi, 1 );
663                         else                    bpi->data= seq_stepdata__internal( bpi, 0 );
664                         if (bpi->data) {
665                                 Sequence *seq= (Sequence *)bpi->data;
666                                 bpi->_lib= NULL;
667                                 bpi->_name= seq->name+2;
668                                 bpi->len= seq->plugin ? sizeof(seq->plugin->name) : sizeof(seq->strip->dir) + sizeof(seq->strip->stripdata->name);
669                                 break;
670                         }
671                         else {
672                                 bpi_type_step__internal(bpi);
673                         }
674                 }
675                 else if  ((bpi->type) == BPATH_CDATA) {
676                         if (bpi->data)  bpi->data= cdata_stepdata__internal( bpi->data, 1 );
677                         else                    bpi->data= cdata_stepdata__internal( bpi->bmain->mesh.first, 0 );
678
679                         if (bpi->data) {
680                                 Mesh *me= (Mesh *)bpi->data;
681                                 bpi->_lib= me->id.lib ? me->id.lib->filepath : NULL;
682                                 bpi->_path= me->fdata.external->filename;
683                                 bpi->_name= me->id.name+2;
684                                 bpi->len= sizeof(me->fdata.external->filename);
685                                 break;
686                         }
687                         else {
688                                 bpi_type_step__internal(bpi);
689                         }
690                 } else if  ((bpi->type) == BPATH_FRS_MODULE) {
691                         if (bpi->data)  bpi->data= frs_module_stepdata__internal( bpi, 1 );
692                         else                    bpi->data= frs_module_stepdata__internal( bpi, 0 );
693
694                         if (bpi->data) {
695                                 FreestyleModuleConfig *module= (FreestyleModuleConfig *)bpi->data;
696                                 bpi->_lib= NULL;
697                                 bpi->_path= module->module_path;
698                                 bpi->_name= NULL;
699                                 bpi->len= sizeof(module->module_path);
700                                 break;
701                         } else {
702                                 bpi_type_step__internal(bpi);
703                         }
704                 }
705         }
706 }
707
708 int BLI_bpathIterator_isDone( struct BPathIterator *bpi)
709 {
710         return bpi->type==BPATH_DONE;
711 }
712
713 /* include the path argument */
714 static void bpath_as_report(struct BPathIterator *bpi, const char *message, ReportList *reports)
715 {
716         const char *prefix;
717         const char *name;
718         char path_expanded[FILE_MAXDIR*2];
719         
720         if(reports==NULL)
721                 return;
722
723         switch(BLI_bpathIterator_getType(bpi)) {
724         case BPATH_IMAGE:
725                 prefix= "Image";
726                 break;
727         case BPATH_TEXTURE:
728                 prefix= "Texture";
729                 break;
730         case BPATH_TEXT:
731                 prefix= "Text";
732                 break;
733         case BPATH_SOUND:
734                 prefix= "Sound";
735                 break;
736         case BPATH_FONT:
737                 prefix= "Font";
738                 break;
739         case BPATH_LIB:
740                 prefix= "Library";
741                 break;
742         case BPATH_SEQ:
743                 prefix= "Sequence";
744                 break;
745         case BPATH_CDATA:
746                 prefix= "Mesh Data";
747                 break;
748         case BPATH_FRS_MODULE:
749                 prefix= "Freestyle Module";
750                 break;
751         default:
752                 prefix= "Unknown";
753                 break;
754         }
755         
756         name= BLI_bpathIterator_getName(bpi);
757         BLI_bpathIterator_getPathExpanded(bpi, path_expanded);
758
759         if(reports) {
760                 if (name)       BKE_reportf(reports, RPT_WARNING, "%s \"%s\", \"%s\": %s", prefix, name, path_expanded, message);
761                 else            BKE_reportf(reports, RPT_WARNING, "%s \"%s\": %s", prefix, path_expanded, message);
762         }
763
764 }
765
766 /* high level function */
767 void checkMissingFiles(Main *bmain, ReportList *reports)
768 {
769         struct BPathIterator *bpi;
770         
771         /* be sure there is low chance of the path being too short */
772         char filepath_expanded[FILE_MAXDIR*2]; 
773         
774         BLI_bpathIterator_init(&bpi, bmain, bmain->name, 0);
775         while (!BLI_bpathIterator_isDone(bpi)) {
776                 BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded);
777                 
778                 if (!BLI_exists(filepath_expanded))
779                         bpath_as_report(bpi, "file not found", reports);
780
781                 BLI_bpathIterator_step(bpi);
782         }
783         BLI_bpathIterator_free(bpi);
784 }
785
786 /* dont log any errors at the moment, should probably do this */
787 void makeFilesRelative(Main *bmain, const char *basedir, ReportList *reports)
788 {
789         int tot= 0, changed= 0, failed= 0, linked= 0;
790         struct BPathIterator *bpi;
791         char filepath[FILE_MAX];
792         const char *libpath;
793         
794         /* be sure there is low chance of the path being too short */
795         char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE];
796
797         if(basedir[0] == '\0') {
798                 printf("makeFilesRelative: basedir='', this is a bug\n");
799                 return;
800         }
801
802         BLI_bpathIterator_init(&bpi, bmain, basedir, 0);
803         while (!BLI_bpathIterator_isDone(bpi)) {
804                 BLI_bpathIterator_getPath(bpi, filepath);
805                 libpath= BLI_bpathIterator_getLib(bpi);
806                 
807                 if(strncmp(filepath, "//", 2)) {
808                         if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */
809                                 linked++;
810                         }
811                         else { /* local data, use the blend files path */
812                                 BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative));
813                                 /* Important BLI_cleanup_dir runs before the path is made relative
814                                  * because it wont work for paths that start with "//../" */ 
815                                 BLI_cleanup_file(bpi->base_path, filepath_relative); /* fix any /foo/../foo/ */
816                                 BLI_path_rel(filepath_relative, bpi->base_path);
817                                 /* be safe and check the length */
818                                 if (BLI_bpathIterator_getPathMaxLen(bpi) <= strlen(filepath_relative)) {
819                                         bpath_as_report(bpi, "couldn't make path relative (too long)", reports);
820                                         failed++;
821                                 }
822                                 else {
823                                         if(strncmp(filepath_relative, "//", 2)==0) {
824                                                 BLI_bpathIterator_setPath(bpi, filepath_relative);
825                                                 changed++;
826                                         }
827                                         else {
828                                                 bpath_as_report(bpi, "couldn't make path relative", reports);
829                                                 failed++;
830                                         }
831                                 }
832                         }
833                 }
834                 BLI_bpathIterator_step(bpi);
835                 tot++;
836         }
837         BLI_bpathIterator_free(bpi);
838
839         if(reports)
840                 BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
841 }
842
843 /* dont log any errors at the moment, should probably do this -
844  * Verry similar to makeFilesRelative - keep in sync! */
845 void makeFilesAbsolute(Main *bmain, const char *basedir, ReportList *reports)
846 {
847         int tot= 0, changed= 0, failed= 0, linked= 0;
848
849         struct BPathIterator *bpi;
850         char filepath[FILE_MAX];
851         const char *libpath;
852         
853         /* be sure there is low chance of the path being too short */
854         char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE];
855
856         if(basedir[0] == '\0') {
857                 printf("makeFilesAbsolute: basedir='', this is a bug\n");
858                 return;
859         }
860
861         BLI_bpathIterator_init(&bpi, bmain, basedir, 0);
862         while (!BLI_bpathIterator_isDone(bpi)) {
863                 BLI_bpathIterator_getPath(bpi, filepath);
864                 libpath= BLI_bpathIterator_getLib(bpi);
865                 
866                 if(strncmp(filepath, "//", 2)==0) {
867                         if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */
868                                 linked++;
869                         }
870                         else { /* get the expanded path and check it is relative or too long */
871                                 BLI_bpathIterator_getPathExpanded(bpi, filepath_absolute);
872                                 BLI_cleanup_file(bpi->base_path, filepath_absolute); /* fix any /foo/../foo/ */
873                                 /* to be safe, check the length */
874                                 if (BLI_bpathIterator_getPathMaxLen(bpi) <= strlen(filepath_absolute)) {
875                                         bpath_as_report(bpi, "couldn't make absolute (too long)", reports);
876                                         failed++;
877                                 }
878                                 else {
879                                         if(strncmp(filepath_absolute, "//", 2)) {
880                                                 BLI_bpathIterator_setPath(bpi, filepath_absolute);
881                                                 changed++;
882                                         }
883                                         else {
884                                                 bpath_as_report(bpi, "couldn't make absolute", reports);
885                                                 failed++;
886                                         }
887                                 }
888                         }
889                 }
890                 BLI_bpathIterator_step(bpi);
891                 tot++;
892         }
893         BLI_bpathIterator_free(bpi);
894
895         if(reports)
896                 BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
897 }
898
899
900 /* find this file recursively, use the biggest file so thumbnails dont get used by mistake
901  - dir: subdir to search
902  - filename: set this filename
903  - filesize: filesize for the file
904 */
905 #define MAX_RECUR 16
906 static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth)
907 {
908         /* file searching stuff */
909         DIR *dir;
910         struct dirent *de;
911         struct stat status;
912         char path[FILE_MAX];
913         int size;
914         
915         dir= opendir(dirname);
916         
917         if (dir==NULL)
918                 return 0;
919         
920         if (*filesize == -1)
921                 *filesize= 0; /* dir opened fine */
922         
923         while ((de= readdir(dir)) != NULL) {
924                 
925                 if (strcmp(".", de->d_name)==0 || strcmp("..", de->d_name)==0)
926                         continue;
927                 
928                 BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
929                 
930                 if (stat(path, &status) != 0)
931                         continue; /* cant stat, dont bother with this file, could print debug info here */
932                 
933                 if (S_ISREG(status.st_mode)) { /* is file */
934                         if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */
935                                 /* open the file to read its size */
936                                 size= status.st_size;
937                                 if ((size > 0) && (size > *filesize)) { /* find the biggest file */
938                                         *filesize= size;
939                                         BLI_strncpy(filename_new, path, FILE_MAX);
940                                 }
941                         }
942                 }
943                 else if (S_ISDIR(status.st_mode)) { /* is subdir */
944                         if (*recur_depth <= MAX_RECUR) {
945                                 (*recur_depth)++;
946                                 findFileRecursive(filename_new, path, filename, filesize, recur_depth);
947                                 (*recur_depth)--;
948                         }
949                 }
950         }
951         closedir(dir);
952         return 1;
953 }
954
955 /* high level function - call from fileselector */
956 void findMissingFiles(Main *bmain, const char *str)
957 {
958         struct BPathIterator *bpi;
959         
960         /* be sure there is low chance of the path being too short */
961         char filepath_expanded[FILE_MAXDIR*2]; 
962         char filepath[FILE_MAX];
963         const char *libpath;
964         int filesize, recur_depth;
965         
966         char dirname[FILE_MAX], filename_new[FILE_MAX];
967         
968         //XXX waitcursor( 1 );
969         
970         BLI_split_dir_part(str, dirname, sizeof(dirname));
971         
972         BLI_bpathIterator_init(&bpi, bmain, bmain->name, 0);
973         
974         while (!BLI_bpathIterator_isDone(bpi)) {
975                 BLI_bpathIterator_getPath(bpi, filepath);
976                 libpath= BLI_bpathIterator_getLib(bpi);
977                 
978                 /* Check if esc was pressed because searching files can be slow */
979                 /*XXX if (blender_test_break()) {
980                         break;
981                 }*/
982                 
983                 if (libpath==NULL) {
984                         
985                         BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded);
986                         
987                         if (!BLI_exists(filepath_expanded)) {
988                                 /* can the dir be opened? */
989                                 filesize= -1;
990                                 recur_depth= 0;
991                                 
992                                 findFileRecursive(filename_new, dirname, BLI_path_basename(filepath), &filesize, &recur_depth);
993                                 if (filesize == -1) { /* could not open dir */
994                                         printf("Could not open dir \"%s\"\n", dirname);
995                                         return;
996                                 }
997                                 
998                                 if (filesize > 0) {
999                                         
1000                                         if (BLI_bpathIterator_getPathMaxLen(bpi) < strlen(filename_new)) { 
1001                                                 printf("cannot set path \"%s\" too long!", filename_new);
1002                                         }
1003                                         else {
1004                                                 /* copy the found path into the old one */
1005                                                 if (G.relbase_valid)
1006                                                         BLI_path_rel(filename_new, bpi->base_path);
1007                                                 
1008                                                 BLI_bpathIterator_setPath(bpi, filename_new);
1009                                         }
1010                                 }
1011                         }
1012                 }
1013                 BLI_bpathIterator_step(bpi);
1014         }
1015         BLI_bpathIterator_free(bpi);
1016         
1017         //XXX waitcursor( 0 );
1018 }