Blender  V2.59
bpath.c
Go to the documentation of this file.
00001 /*
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): Campbell barton
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <sys/stat.h>
00035 
00036 #include <string.h>
00037 #include <assert.h>
00038 
00039 /* path/file handeling stuff */
00040 #ifndef WIN32
00041   #include <dirent.h>
00042   #include <unistd.h>
00043 #else
00044   #include <io.h>
00045   #include "BLI_winstuff.h"
00046 #endif
00047 
00048 #include "MEM_guardedalloc.h"
00049 
00050 #include "DNA_mesh_types.h"
00051 #include "DNA_scene_types.h" /* to get the current frame */
00052 #include "DNA_image_types.h"
00053 #include "DNA_texture_types.h"
00054 #include "DNA_text_types.h"
00055 #include "DNA_sound_types.h"
00056 #include "DNA_sequence_types.h"
00057 #include "DNA_vfont_types.h"
00058 #include "DNA_windowmanager_types.h"
00059 
00060 #include "BLI_blenlib.h"
00061 #include "BLI_bpath.h"
00062 #include "BLI_utildefines.h"
00063 
00064 #include "BKE_global.h"
00065 #include "BKE_image.h" /* so we can check the image's type */
00066 #include "BKE_sequencer.h"
00067 #include "BKE_main.h"
00068 #include "BKE_utildefines.h"
00069 #include "BKE_report.h"
00070 
00071 typedef struct BPathIteratorSeqData
00072 {
00073         int totseq;
00074         int seq;
00075         struct Sequence **seqar;        /* Sequence */
00076         struct Scene *scene;            /* Current scene */
00077 } BPathIteratorSeqData;
00078 
00079 typedef struct BPathIterator
00080 {
00081         char*   _path; /* never access directly, use BLI_bpathIterator_getPath */
00082         const char*     _lib;
00083         const char*     _name;
00084         void*   data;
00085         int             len;
00086         int             type;
00087         int             flag; /* iterator options */
00088 
00089         void (*setpath_callback)(struct BPathIterator *, const char *);
00090         void (*getpath_callback)(struct BPathIterator *, char *);
00091 
00092         const char*     base_path; /* base path, the directory the blend file is in - normally bmain->name */
00093 
00094         Main *bmain;
00095 
00096         /* only for seq data */
00097         struct BPathIteratorSeqData seqdata;
00098 } BPathIterator;
00099 
00100 #define FILE_MAX                        240
00101 
00102 
00103 /* TODO - BPATH_PLUGIN, BPATH_SEQ */
00104 enum BPathTypes {
00105         BPATH_IMAGE= 0,
00106         BPATH_TEXTURE,
00107         BPATH_TEXT,
00108         BPATH_SOUND,
00109         BPATH_FONT,
00110         BPATH_LIB,
00111         BPATH_SEQ,
00112         BPATH_CDATA,
00113 
00114         BPATH_DONE
00115 };
00116 
00117 void BLI_bpathIterator_init(struct BPathIterator **bpi_pt, Main *bmain, const char *basedir, const int flag)
00118 {
00119         BPathIterator *bpi;
00120 
00121         bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_init");
00122         *bpi_pt= bpi;
00123 
00124         bpi->type= BPATH_IMAGE;
00125         bpi->data= NULL;
00126 
00127         bpi->getpath_callback= NULL;
00128         bpi->setpath_callback= NULL;
00129 
00130         /* Sequencer specific */
00131         bpi->seqdata.totseq= 0;
00132         bpi->seqdata.seq= 0;
00133         bpi->seqdata.seqar= NULL;
00134         bpi->seqdata.scene= NULL;
00135 
00136         bpi->flag= flag;
00137 
00138         bpi->base_path= basedir; /* normally bmain->name */
00139         bpi->bmain= bmain;
00140 
00141         BLI_bpathIterator_step(bpi);
00142 }
00143 
00144 #if 0
00145 static void BLI_bpathIterator_alloc(struct BPathIterator **bpi)
00146 {
00147         *bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_alloc");
00148 }
00149 #endif
00150 
00151 void BLI_bpathIterator_free(struct BPathIterator *bpi)
00152 {
00153         if (bpi->seqdata.seqar)
00154                 MEM_freeN((void *)bpi->seqdata.seqar);
00155         bpi->seqdata.seqar= NULL;
00156         bpi->seqdata.scene= NULL;
00157 
00158         MEM_freeN(bpi);
00159 }
00160 
00161 void BLI_bpathIterator_getPath(struct BPathIterator *bpi, char *path)
00162 {
00163         if (bpi->getpath_callback) {
00164                 bpi->getpath_callback(bpi, path);
00165         }
00166         else {
00167                 strcpy(path, bpi->_path); /* warning, we assume 'path' are long enough */
00168         }
00169 }
00170 
00171 void BLI_bpathIterator_setPath(struct BPathIterator *bpi, const char *path)
00172 {
00173         if (bpi->setpath_callback) {
00174                 bpi->setpath_callback(bpi, path);
00175         }
00176         else {
00177                 strcpy(bpi->_path, path); /* warning, we assume 'path' are long enough */
00178         }
00179 }
00180 
00181 void BLI_bpathIterator_getPathExpanded(struct BPathIterator *bpi, char *path_expanded)
00182 {
00183         const char *libpath;
00184 
00185         BLI_bpathIterator_getPath(bpi, path_expanded);
00186         libpath= BLI_bpathIterator_getLib(bpi);
00187 
00188         if (libpath) { /* check the files location relative to its library path */
00189                 BLI_path_abs(path_expanded, libpath);
00190         }
00191         else { /* local data, use the blend files path */
00192                 BLI_path_abs(path_expanded, bpi->base_path);
00193         }
00194         BLI_cleanup_file(NULL, path_expanded);
00195 }
00196 const char* BLI_bpathIterator_getLib(struct BPathIterator *bpi)
00197 {
00198         return bpi->_lib;
00199 }
00200 const char* BLI_bpathIterator_getName(struct BPathIterator *bpi)
00201 {
00202         return bpi->_name;
00203 }
00204 int     BLI_bpathIterator_getType(struct BPathIterator *bpi)
00205 {
00206         return bpi->type;
00207 }
00208 unsigned int    BLI_bpathIterator_getPathMaxLen(struct BPathIterator *bpi)
00209 {
00210         return bpi->len;
00211 }
00212 const char* BLI_bpathIterator_getBasePath(struct BPathIterator *bpi)
00213 {
00214         return bpi->base_path;
00215 }
00216 
00217 /* gets the first or the next image that has a path - not a viewer node or generated image */
00218 static struct Image *ima_stepdata__internal(struct Image *ima, const int step_next, const int flag)
00219 {
00220         if (ima==NULL)
00221                 return NULL;
00222 
00223         if (step_next)
00224                 ima= ima->id.next;
00225 
00226         while (ima) {
00227                 if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
00228                         if(ima->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
00229                                 break;
00230                         }
00231                 }
00232                 /* image is not a image with a path, skip it */
00233                 ima= ima->id.next;
00234         }
00235         return ima;
00236 }
00237 
00238 static struct Tex *tex_stepdata__internal(struct Tex *tex, const int step_next, const int UNUSED(flag))
00239 {
00240         if (tex==NULL)
00241                 return NULL;
00242 
00243         if (step_next)
00244                 tex= tex->id.next;
00245 
00246         while (tex) {
00247                 if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format))
00248                         break;
00249                 /* image is not a image with a path, skip it */
00250                 tex= tex->id.next;
00251         }
00252         return tex;
00253 }
00254 
00255 static struct Text *text_stepdata__internal(struct Text *text, const int step_next, const int UNUSED(flag))
00256 {
00257         if (text==NULL)
00258                 return NULL;
00259 
00260         if (step_next)
00261                 text= text->id.next;
00262 
00263         while (text) {
00264                 if (text->name)
00265                         break;
00266                 /* image is not a image with a path, skip it */
00267                 text= text->id.next;
00268         }
00269         return text;
00270 }
00271 
00272 static struct VFont *vf_stepdata__internal(struct VFont *vf, const int step_next, const int flag)
00273 {
00274         if (vf==NULL)
00275                 return NULL;
00276 
00277         if (step_next)
00278                 vf= vf->id.next;
00279 
00280         while (vf) {
00281                 if (strcmp(vf->name, FO_BUILTIN_NAME)!=0) {
00282                         if(vf->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
00283                                 break;
00284                         }
00285                 }
00286 
00287                 /* font with no path, skip it */
00288                 vf= vf->id.next;
00289         }
00290         return vf;
00291 }
00292 
00293 static struct bSound *snd_stepdata__internal(struct bSound *snd, int step_next, const int flag)
00294 {
00295         if (snd==NULL)
00296                 return NULL;
00297 
00298         if (step_next)
00299                 snd= snd->id.next;
00300 
00301         while (snd) {
00302                 if(snd->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
00303                         break;
00304                 }
00305 
00306                 /* font with no path, skip it */
00307                 snd= snd->id.next;
00308         }
00309         return snd;
00310 }
00311 
00312 static struct Sequence *seq_stepdata__internal(struct BPathIterator *bpi, int step_next)
00313 {
00314         Editing *ed;
00315         Sequence *seq;
00316 
00317         /* Initializing */
00318         if (bpi->seqdata.scene==NULL) {
00319                 bpi->seqdata.scene= bpi->bmain->scene.first;
00320         }
00321 
00322         if (step_next) {
00323                 bpi->seqdata.seq++;
00324         }
00325 
00326         while (bpi->seqdata.scene) {
00327                 ed= seq_give_editing(bpi->seqdata.scene, 0);
00328                 if (ed) {
00329                         if (bpi->seqdata.seqar == NULL) {
00330                                 /* allocate the sequencer array */
00331                                 seq_array(ed, &bpi->seqdata.seqar, &bpi->seqdata.totseq, 0);
00332                                 bpi->seqdata.seq= 0;
00333                         }
00334 
00335                         if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
00336                                 seq= NULL;
00337                         }
00338                         else {
00339                                 seq= bpi->seqdata.seqar[bpi->seqdata.seq];
00340                                 while (!SEQ_HAS_PATH(seq) && seq->plugin==NULL) {
00341                                         bpi->seqdata.seq++;
00342                                         if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
00343                                                 seq= NULL;
00344                                                 break;
00345                                         }
00346                                         seq= bpi->seqdata.seqar[bpi->seqdata.seq];
00347                                 }
00348                         }
00349                         if (seq) {
00350                                 return seq;
00351                         }
00352                         else {
00353                                 /* keep looking through the next scene, reallocate seq array */
00354                                 if (bpi->seqdata.seqar) {
00355                                         MEM_freeN((void *)bpi->seqdata.seqar);
00356                                         bpi->seqdata.seqar= NULL;
00357                                 }
00358                                 bpi->seqdata.scene= bpi->seqdata.scene->id.next;
00359                         }
00360                 }
00361                 else {
00362                         /* no seq data in this scene, next */
00363                         bpi->seqdata.scene= bpi->seqdata.scene->id.next;
00364                 }
00365         }
00366 
00367         return NULL;
00368 }
00369 
00370 static void seq_getpath(struct BPathIterator *bpi, char *path)
00371 {
00372         Sequence *seq= (Sequence *)bpi->data;
00373 
00374 
00375         path[0]= '\0'; /* incase we cant get the path */
00376         if (seq==NULL) return;
00377         if (SEQ_HAS_PATH(seq)) {
00378                 if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
00379                         BLI_strncpy(path, seq->strip->dir, FILE_MAX);
00380                         BLI_add_slash(path); /* incase its missing */
00381                         if (seq->strip->stripdata) { /* should always be true! */
00382                                 /* Using the first image is weak for image sequences */
00383                                 strcat(path, seq->strip->stripdata->name);
00384                         }
00385                 }
00386                 else {
00387                         /* simple case */
00388                         BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
00389                 }
00390         }
00391         else if (seq->plugin) {
00392                 BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name));
00393         }
00394 }
00395 
00396 static void seq_setpath(struct BPathIterator *bpi, const char *path)
00397 {
00398         Sequence *seq= (Sequence *)bpi->data;
00399         if (seq==NULL) return;
00400 
00401         if (SEQ_HAS_PATH(seq)) {
00402                 if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
00403                         BLI_split_dirfile(path, seq->strip->dir, seq->strip->stripdata->name);
00404                 }
00405                 else {
00406                         /* simple case */
00407                         BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
00408                 }
00409         }
00410         else if (seq->plugin) {
00411                 BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name));
00412         }
00413 }
00414 
00415 static void text_getpath(struct BPathIterator *bpi, char *path)
00416 {
00417         Text *text= (Text *)bpi->data;
00418         path[0]= '\0'; /* incase we cant get the path */
00419         if(text->name) {
00420                 strcpy(path, text->name);
00421         }
00422 }
00423 
00424 static void text_setpath(struct BPathIterator *bpi, const char *path)
00425 {
00426         Text *text= (Text *)bpi->data;
00427         if (text==NULL) return;
00428 
00429         if(text->name) {
00430                 MEM_freeN(text->name);
00431         }
00432 
00433         text->name= BLI_strdup(path);
00434 }
00435 
00436 static struct Mesh *cdata_stepdata__internal(struct Mesh *me, int step_next)
00437 {
00438         if (me==NULL)
00439                 return NULL;
00440 
00441         if (step_next)
00442                 me= me->id.next;
00443 
00444         while (me) {
00445                 if (me->fdata.external) {
00446                         break;
00447                 }
00448 
00449                 me= me->id.next;
00450         }
00451         return me;
00452 }
00453 
00454 static void bpi_type_step__internal(struct BPathIterator *bpi)
00455 {
00456         bpi->type++; /* advance to the next type */
00457         bpi->data= NULL;
00458 
00459         switch (bpi->type) {
00460         case BPATH_SEQ:
00461                 bpi->getpath_callback= seq_getpath;
00462                 bpi->setpath_callback= seq_setpath;
00463                 break;
00464         case BPATH_TEXT: /* path is malloc'd */
00465                 bpi->getpath_callback= text_getpath;
00466                 bpi->setpath_callback= text_setpath;
00467                 break;
00468         default:
00469                 bpi->getpath_callback= NULL;
00470                 bpi->setpath_callback= NULL;
00471                 break;
00472         }
00473 }
00474 
00475 void BLI_bpathIterator_step(struct BPathIterator *bpi)
00476 {
00477         while (bpi->type != BPATH_DONE) {
00478 
00479                 if  ((bpi->type) == BPATH_IMAGE) {
00480                         /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
00481                         if (bpi->data)  bpi->data= ima_stepdata__internal((Image *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
00482                         else                    bpi->data= ima_stepdata__internal(bpi->bmain->image.first, 0, bpi->flag);
00483 
00484                         if (bpi->data) {
00485                                 /* get the path info from this datatype */
00486                                 Image *ima= (Image *)bpi->data;
00487 
00488                                 bpi->_lib= ima->id.lib ? ima->id.lib->filepath : NULL;
00489                                 bpi->_path= ima->name;
00490                                 bpi->_name= ima->id.name+2;
00491                                 bpi->len= sizeof(ima->name);
00492 
00493                                 /* we are done, advancing to the next item, this type worked fine */
00494                                 break;
00495 
00496                         }
00497                         else {
00498                                 bpi_type_step__internal(bpi);
00499                         }
00500                 }
00501 
00502                 if  ((bpi->type) == BPATH_TEXTURE) {
00503                         /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
00504                         if (bpi->data)  bpi->data= tex_stepdata__internal( (Tex *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
00505                         else                    bpi->data= tex_stepdata__internal(bpi->bmain->tex.first, 0, bpi->flag);
00506 
00507                         if (bpi->data) {
00508                                 /* get the path info from this datatype */
00509                                 Tex *tex= (Tex *)bpi->data;
00510 
00511                                 if(tex->type == TEX_VOXELDATA) {
00512                                         bpi->_lib= tex->id.lib ? tex->id.lib->filepath : NULL;
00513                                         bpi->_path= tex->vd->source_path;
00514                                         bpi->_name= tex->id.name+2;
00515                                         bpi->len= sizeof(tex->vd->source_path);
00516                                 }
00517                                 else {
00518                                         assert(!"Texture has no path, incorrect step 'tex_stepdata__internal'");
00519                                 }
00520 
00521                                 /* we are done, advancing to the next item, this type worked fine */
00522                                 break;
00523 
00524                         }
00525                         else {
00526                                 bpi_type_step__internal(bpi);
00527                         }
00528                 }
00529 
00530                 if  ((bpi->type) == BPATH_TEXT) {
00531                         /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
00532                         if (bpi->data)  bpi->data= text_stepdata__internal((Text *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
00533                         else                    bpi->data= text_stepdata__internal(bpi->bmain->text.first, 0, bpi->flag);
00534 
00535                         if (bpi->data) {
00536                                 /* get the path info from this datatype */
00537                                 Text *text= (Text *)bpi->data;
00538 
00539                                 bpi->_lib= text->id.lib ? text->id.lib->filepath : NULL;
00540                                 bpi->_path= NULL; /* bpi->path= text->name; */ /* get/set functions override. */
00541                                 bpi->_name= text->id.name+2;
00542                                 bpi->len= FILE_MAX; /* malloc'd but limit anyway since large paths may mess up other areas */
00543 
00544                                 /* we are done, advancing to the next item, this type worked fine */
00545                                 break;
00546 
00547                         }
00548                         else {
00549                                 bpi_type_step__internal(bpi);
00550                         }
00551                 }
00552                 else if  ((bpi->type) == BPATH_SOUND) {
00553                         if (bpi->data)  bpi->data= snd_stepdata__internal((bSound *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
00554                         else                    bpi->data= snd_stepdata__internal(bpi->bmain->sound.first, 0, bpi->flag);
00555 
00556                         if (bpi->data) {
00557                                 /* get the path info from this datatype */
00558                                 bSound *snd= (bSound *)bpi->data;
00559 
00560                                 bpi->_lib= snd->id.lib ? snd->id.lib->filepath : NULL;
00561                                 bpi->_path= snd->name;
00562                                 bpi->_name= snd->id.name+2;
00563                                 bpi->len= sizeof(snd->name);
00564 
00565                                 /* we are done, advancing to the next item, this type worked fine */
00566                                 break;
00567                         }
00568                         else {
00569                                 bpi_type_step__internal(bpi);
00570                         }
00571                 }
00572                 else if  ((bpi->type) == BPATH_FONT) {
00573 
00574                         if (bpi->data)  bpi->data= vf_stepdata__internal((VFont *)bpi->data, 1, bpi->flag);
00575                         else                    bpi->data= vf_stepdata__internal(bpi->bmain->vfont.first, 0, bpi->flag);
00576 
00577                         if (bpi->data) {
00578                                 /* get the path info from this datatype */
00579                                 VFont *vf= (VFont *)bpi->data;
00580 
00581                                 bpi->_lib= vf->id.lib ? vf->id.lib->filepath : NULL;
00582                                 bpi->_path= vf->name;
00583                                 bpi->_name= vf->id.name+2;
00584                                 bpi->len= sizeof(vf->name);
00585 
00586                                 /* we are done, advancing to the next item, this type worked fine */
00587                                 break;
00588                         }
00589                         else {
00590                                 bpi_type_step__internal(bpi);
00591                         }
00592 
00593                 }
00594                 else if  ((bpi->type) == BPATH_LIB) {
00595                         if (bpi->data)  bpi->data= ((ID *)bpi->data)->next;
00596                         else                    bpi->data= bpi->bmain->library.first;
00597 
00598                         if (bpi->data) {
00599                                 /* get the path info from this datatype */
00600                                 Library *lib= (Library *)bpi->data;
00601 
00602                                 bpi->_lib= NULL;
00603                                 bpi->_path= lib->name;
00604                                 bpi->_name= NULL;
00605                                 bpi->len= sizeof(lib->name);
00606 
00607                                 /* we are done, advancing to the next item, this type worked fine */
00608                                 break;
00609                         }
00610                         else {
00611                                 bpi_type_step__internal(bpi);
00612                         }
00613                 }
00614                 else if  ((bpi->type) == BPATH_SEQ) {
00615                         if (bpi->data)  bpi->data= seq_stepdata__internal( bpi, 1 );
00616                         else                    bpi->data= seq_stepdata__internal( bpi, 0 );
00617                         if (bpi->data) {
00618                                 Sequence *seq= (Sequence *)bpi->data;
00619                                 bpi->_lib= NULL;
00620                                 bpi->_name= seq->name+2;
00621                                 bpi->len= seq->plugin ? sizeof(seq->plugin->name) : sizeof(seq->strip->dir) + sizeof(seq->strip->stripdata->name);
00622                                 break;
00623                         }
00624                         else {
00625                                 bpi_type_step__internal(bpi);
00626                         }
00627                 }
00628                 else if  ((bpi->type) == BPATH_CDATA) {
00629                         if (bpi->data)  bpi->data= cdata_stepdata__internal( bpi->data, 1 );
00630                         else                    bpi->data= cdata_stepdata__internal( bpi->bmain->mesh.first, 0 );
00631 
00632                         if (bpi->data) {
00633                                 Mesh *me= (Mesh *)bpi->data;
00634                                 bpi->_lib= me->id.lib ? me->id.lib->filepath : NULL;
00635                                 bpi->_path= me->fdata.external->filename;
00636                                 bpi->_name= me->id.name+2;
00637                                 bpi->len= sizeof(me->fdata.external->filename);
00638                                 break;
00639                         }
00640                         else {
00641                                 bpi_type_step__internal(bpi);
00642                         }
00643                 }
00644         }
00645 }
00646 
00647 int BLI_bpathIterator_isDone( struct BPathIterator *bpi) {
00648         return bpi->type==BPATH_DONE;
00649 }
00650 
00651 /* include the path argument */
00652 static void bpath_as_report(struct BPathIterator *bpi, const char *message, ReportList *reports)
00653 {
00654         const char *prefix;
00655         const char *name;
00656         char path_expanded[FILE_MAXDIR*2];
00657 
00658         if(reports==NULL)
00659                 return;
00660 
00661         switch(BLI_bpathIterator_getType(bpi)) {
00662         case BPATH_IMAGE:
00663                 prefix= "Image";
00664                 break;
00665         case BPATH_TEXTURE:
00666                 prefix= "Texture";
00667                 break;
00668         case BPATH_TEXT:
00669                 prefix= "Text";
00670                 break;
00671         case BPATH_SOUND:
00672                 prefix= "Sound";
00673                 break;
00674         case BPATH_FONT:
00675                 prefix= "Font";
00676                 break;
00677         case BPATH_LIB:
00678                 prefix= "Library";
00679                 break;
00680         case BPATH_SEQ:
00681                 prefix= "Sequence";
00682                 break;
00683         case BPATH_CDATA:
00684                 prefix= "Mesh Data";
00685                 break;
00686         default:
00687                 prefix= "Unknown";
00688                 break;
00689         }
00690 
00691         name= BLI_bpathIterator_getName(bpi);
00692         BLI_bpathIterator_getPathExpanded(bpi, path_expanded);
00693 
00694         if(reports) {
00695                 if (name)       BKE_reportf(reports, RPT_WARNING, "%s \"%s\", \"%s\": %s", prefix, name, path_expanded, message);
00696                 else            BKE_reportf(reports, RPT_WARNING, "%s \"%s\": %s", prefix, path_expanded, message);
00697         }
00698 
00699 }
00700 
00701 /* high level function */
00702 void checkMissingFiles(Main *bmain, ReportList *reports) {
00703         struct BPathIterator *bpi;
00704 
00705         /* be sure there is low chance of the path being too short */
00706         char filepath_expanded[FILE_MAXDIR*2];
00707 
00708         BLI_bpathIterator_init(&bpi, bmain, bmain->name, 0);
00709         while (!BLI_bpathIterator_isDone(bpi)) {
00710                 BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded);
00711 
00712                 if (!BLI_exists(filepath_expanded))
00713                         bpath_as_report(bpi, "file not found", reports);
00714 
00715                 BLI_bpathIterator_step(bpi);
00716         }
00717         BLI_bpathIterator_free(bpi);
00718 }
00719 
00720 /* dont log any errors at the moment, should probably do this */
00721 void makeFilesRelative(Main *bmain, const char *basedir, ReportList *reports) {
00722         int tot= 0, changed= 0, failed= 0, linked= 0;
00723         struct BPathIterator *bpi;
00724         char filepath[FILE_MAX];
00725         const char *libpath;
00726 
00727         /* be sure there is low chance of the path being too short */
00728         char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE];
00729 
00730         if(basedir[0] == '\0') {
00731                 printf("makeFilesRelative: basedir='', this is a bug\n");
00732                 return;
00733         }
00734 
00735         BLI_bpathIterator_init(&bpi, bmain, basedir, 0);
00736         while (!BLI_bpathIterator_isDone(bpi)) {
00737                 BLI_bpathIterator_getPath(bpi, filepath);
00738                 libpath= BLI_bpathIterator_getLib(bpi);
00739 
00740                 if(strncmp(filepath, "//", 2)) {
00741                         if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */
00742                                 linked++;
00743                         }
00744                         else { /* local data, use the blend files path */
00745                                 BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative));
00746                                 /* Important BLI_cleanup_dir runs before the path is made relative
00747                                  * because it wont work for paths that start with "//../" */
00748                                 BLI_cleanup_file(bpi->base_path, filepath_relative); /* fix any /foo/../foo/ */
00749                                 BLI_path_rel(filepath_relative, bpi->base_path);
00750                                 /* be safe and check the length */
00751                                 if (BLI_bpathIterator_getPathMaxLen(bpi) <= strlen(filepath_relative)) {
00752                                         bpath_as_report(bpi, "couldn't make path relative (too long)", reports);
00753                                         failed++;
00754                                 }
00755                                 else {
00756                                         if(strncmp(filepath_relative, "//", 2)==0) {
00757                                                 BLI_bpathIterator_setPath(bpi, filepath_relative);
00758                                                 changed++;
00759                                         }
00760                                         else {
00761                                                 bpath_as_report(bpi, "couldn't make path relative", reports);
00762                                                 failed++;
00763                                         }
00764                                 }
00765                         }
00766                 }
00767                 BLI_bpathIterator_step(bpi);
00768                 tot++;
00769         }
00770         BLI_bpathIterator_free(bpi);
00771 
00772         if(reports)
00773                 BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
00774 }
00775 
00776 /* dont log any errors at the moment, should probably do this -
00777  * Verry similar to makeFilesRelative - keep in sync! */
00778 void makeFilesAbsolute(Main *bmain, const char *basedir, ReportList *reports)
00779 {
00780         int tot= 0, changed= 0, failed= 0, linked= 0;
00781 
00782         struct BPathIterator *bpi;
00783         char filepath[FILE_MAX];
00784         const char *libpath;
00785 
00786         /* be sure there is low chance of the path being too short */
00787         char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE];
00788 
00789         if(basedir[0] == '\0') {
00790                 printf("makeFilesAbsolute: basedir='', this is a bug\n");
00791                 return;
00792         }
00793 
00794         BLI_bpathIterator_init(&bpi, bmain, basedir, 0);
00795         while (!BLI_bpathIterator_isDone(bpi)) {
00796                 BLI_bpathIterator_getPath(bpi, filepath);
00797                 libpath= BLI_bpathIterator_getLib(bpi);
00798 
00799                 if(strncmp(filepath, "//", 2)==0) {
00800                         if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */
00801                                 linked++;
00802                         }
00803                         else { /* get the expanded path and check it is relative or too long */
00804                                 BLI_bpathIterator_getPathExpanded(bpi, filepath_absolute);
00805                                 BLI_cleanup_file(bpi->base_path, filepath_absolute); /* fix any /foo/../foo/ */
00806                                 /* to be safe, check the length */
00807                                 if (BLI_bpathIterator_getPathMaxLen(bpi) <= strlen(filepath_absolute)) {
00808                                         bpath_as_report(bpi, "couldn't make absolute (too long)", reports);
00809                                         failed++;
00810                                 }
00811                                 else {
00812                                         if(strncmp(filepath_absolute, "//", 2)) {
00813                                                 BLI_bpathIterator_setPath(bpi, filepath_absolute);
00814                                                 changed++;
00815                                         }
00816                                         else {
00817                                                 bpath_as_report(bpi, "couldn't make absolute", reports);
00818                                                 failed++;
00819                                         }
00820                                 }
00821                         }
00822                 }
00823                 BLI_bpathIterator_step(bpi);
00824                 tot++;
00825         }
00826         BLI_bpathIterator_free(bpi);
00827 
00828         if(reports)
00829                 BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
00830 }
00831 
00832 
00833 /* find this file recursively, use the biggest file so thumbnails dont get used by mistake
00834  - dir: subdir to search
00835  - filename: set this filename
00836  - filesize: filesize for the file
00837 */
00838 #define MAX_RECUR 16
00839 static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth)
00840 {
00841         /* file searching stuff */
00842         DIR *dir;
00843         struct dirent *de;
00844         struct stat status;
00845         char path[FILE_MAX];
00846         int size;
00847 
00848         dir= opendir(dirname);
00849 
00850         if (dir==NULL)
00851                 return 0;
00852 
00853         if (*filesize == -1)
00854                 *filesize= 0; /* dir opened fine */
00855 
00856         while ((de= readdir(dir)) != NULL) {
00857 
00858                 if (strcmp(".", de->d_name)==0 || strcmp("..", de->d_name)==0)
00859                         continue;
00860 
00861                 BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
00862 
00863                 if (stat(path, &status) != 0)
00864                         continue; /* cant stat, dont bother with this file, could print debug info here */
00865 
00866                 if (S_ISREG(status.st_mode)) { /* is file */
00867                         if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */
00868                                 /* open the file to read its size */
00869                                 size= status.st_size;
00870                                 if ((size > 0) && (size > *filesize)) { /* find the biggest file */
00871                                         *filesize= size;
00872                                         BLI_strncpy(filename_new, path, FILE_MAX);
00873                                 }
00874                         }
00875                 }
00876                 else if (S_ISDIR(status.st_mode)) { /* is subdir */
00877                         if (*recur_depth <= MAX_RECUR) {
00878                                 (*recur_depth)++;
00879                                 findFileRecursive(filename_new, path, filename, filesize, recur_depth);
00880                                 (*recur_depth)--;
00881                         }
00882                 }
00883         }
00884         closedir(dir);
00885         return 1;
00886 }
00887 
00888 /* high level function - call from fileselector */
00889 void findMissingFiles(Main *bmain, const char *str) {
00890         struct BPathIterator *bpi;
00891 
00892         /* be sure there is low chance of the path being too short */
00893         char filepath_expanded[FILE_MAXDIR*2];
00894         char filepath[FILE_MAX];
00895         const char *libpath;
00896         int filesize, recur_depth;
00897 
00898         char dirname[FILE_MAX], filename_new[FILE_MAX];
00899 
00900         //XXX waitcursor( 1 );
00901 
00902         BLI_split_dirfile(str, dirname, NULL);
00903 
00904         BLI_bpathIterator_init(&bpi, bmain, bmain->name, 0);
00905 
00906         while (!BLI_bpathIterator_isDone(bpi)) {
00907                 BLI_bpathIterator_getPath(bpi, filepath);
00908                 libpath= BLI_bpathIterator_getLib(bpi);
00909 
00910                 /* Check if esc was pressed because searching files can be slow */
00911                 /*XXX if (blender_test_break()) {
00912                         break;
00913                 }*/
00914 
00915                 if (libpath==NULL) {
00916 
00917                         BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded);
00918 
00919                         if (!BLI_exists(filepath_expanded)) {
00920                                 /* can the dir be opened? */
00921                                 filesize= -1;
00922                                 recur_depth= 0;
00923 
00924                                 findFileRecursive(filename_new, dirname, BLI_path_basename(filepath), &filesize, &recur_depth);
00925                                 if (filesize == -1) { /* could not open dir */
00926                                         printf("Could not open dir \"%s\"\n", dirname);
00927                                         return;
00928                                 }
00929 
00930                                 if (filesize > 0) {
00931 
00932                                         if (BLI_bpathIterator_getPathMaxLen(bpi) < strlen(filename_new)) {
00933                                                 printf("cannot set path \"%s\" too long!", filename_new);
00934                                         }
00935                                         else {
00936                                                 /* copy the found path into the old one */
00937                                                 if (G.relbase_valid)
00938                                                         BLI_path_rel(filename_new, bpi->base_path);
00939 
00940                                                 BLI_bpathIterator_setPath(bpi, filename_new);
00941                                         }
00942                                 }
00943                         }
00944                 }
00945                 BLI_bpathIterator_step(bpi);
00946         }
00947         BLI_bpathIterator_free(bpi);
00948 
00949         //XXX waitcursor( 0 );
00950 }