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