fffc74e822a061bd44c894bdfad3047a975d2c7a
[blender.git] / source / blender / blenlib / intern / path_util.c
1 /**
2  *  $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  * various string, file, list operations.
30  */
31
32 #include <ctype.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <assert.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_userdef_types.h"
40
41 #include "BLI_fileops.h"
42 #include "BLI_path_util.h"
43 #include "BLI_string.h"
44 #include "BLI_storage.h"
45 #include "BLI_storage_types.h"
46
47 #include "BKE_utildefines.h"
48 #include "BKE_blender.h"        // BLENDER_VERSION
49
50 #include "GHOST_Path-api.h"
51
52 #if defined WIN32 && !defined _LIBC
53 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
54 #else
55 # define _GNU_SOURCE
56 # include <fnmatch.h>
57 #endif
58
59 #ifdef WIN32
60 #include <io.h>
61
62 #ifdef _WIN32_IE
63 #undef _WIN32_IE
64 #endif
65 #define _WIN32_IE 0x0501
66 #include <windows.h>
67 #include <shlobj.h>
68
69 #include "BLI_winstuff.h"
70
71 #else /* non windows */
72
73 #ifdef __linux__
74 #include "binreloc.h"
75 #endif
76
77 #endif /* WIN32 */
78
79 /* local */
80 #define UNIQUE_NAME_MAX 128
81
82 static int add_win32_extension(char *name);
83 static char *blender_version_decimal(void);
84
85 /* implementation */
86
87 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
88 {
89         unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
90         short i, found = 0;
91         char *lslash = BLI_last_slash(string);
92         len2 = len = strlen(string);
93         if(lslash)
94                 lenlslash= (int)(lslash - string);
95
96         while(len > lenlslash && string[--len] != '.') {};
97         if(len == lenlslash && string[len] != '.') len = len2;
98
99         for (i = len - 1; i >= lenlslash; i--) {
100                 if (isdigit(string[i])) {
101                         if (found){
102                                 nums = i;
103                         }
104                         else{
105                                 nume = i;
106                                 nums = i;
107                                 found = 1;
108                         }
109                 }
110                 else {
111                         if (found) break;
112                 }
113         }
114         if (found) {
115                 if (tail) strcpy(tail, &string[nume+1]);
116                 if (head) {
117                         strcpy(head,string);
118                         head[nums]=0;
119                 }
120                 if (numlen) *numlen = nume-nums+1;
121                 return ((int)atoi(&(string[nums])));
122         }
123         if (tail) strcpy(tail, string + len);
124         if (head) {
125                 strncpy(head, string, len);
126                 head[len] = '\0';
127         }
128         if (numlen) *numlen=0;
129         return 0;
130 }
131
132
133 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
134 {
135         char fmtstr[16]="";
136         if(pic < 0) pic= 0;
137         sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
138         sprintf(string, fmtstr, head, pic, tail);
139 }
140
141 /* Foo.001 -> "Foo", 1
142  * Returns the length of "Foo" */
143 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
144 {
145         int a;
146         
147         *nr= 0;
148         a= strlen(name);
149         memcpy(left, name, (a + 1) * sizeof(char));
150
151         if(a>1 && name[a-1]==delim) return a;
152         
153         while(a--) {
154                 if( name[a]==delim ) {
155                         left[a]= 0;
156                         *nr= atol(name+a+1);
157                         /* casting down to an int, can overflow for large numbers */
158                         if(*nr < 0)
159                                 *nr= 0;
160                         return a;
161                 }
162                 if( isdigit(name[a])==0 ) break;
163                 
164                 left[a]= 0;
165         }
166
167         for(a= 0; name[a]; a++)
168                 left[a]= name[a];
169
170         return a;
171 }
172
173 void BLI_newname(char *name, int add)
174 {
175         char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
176         int pic;
177         unsigned short digits;
178         
179         pic = BLI_stringdec(name, head, tail, &digits);
180         
181         /* are we going from 100 -> 99 or from 10 -> 9 */
182         if (add < 0 && digits < 4 && digits > 0) {
183                 int i, exp;
184                 exp = 1;
185                 for (i = digits; i > 1; i--) exp *= 10;
186                 if (pic >= exp && (pic + add) < exp) digits--;
187         }
188         
189         pic += add;
190         
191         if (digits==4 && pic<0) pic= 0;
192         BLI_stringenc(name, head, tail, digits, pic);
193 }
194
195
196
197 int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
198 {
199         if(name == '\0') {
200                 BLI_strncpy(name, defname, name_len);
201         }
202
203         if(unique_check(arg, name)) {
204                 char    tempname[UNIQUE_NAME_MAX];
205                 char    left[UNIQUE_NAME_MAX];
206                 int             number;
207                 int             len= BLI_split_name_num(left, &number, name, delim);
208                 do {    /* nested while loop looks bad but likely it wont run most times */
209                         while(BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, number) >= name_len) {
210                                 if(len > 0)     left[--len]= '\0';      /* word too long */
211                                 else            number= 0;                      /* reset, must be a massive number */
212                         }
213                 } while(number++, unique_check(arg, tempname));
214
215                 BLI_strncpy(name, tempname, name_len);
216                 
217                 return 1;
218         }
219         
220         return 0;
221 }
222
223 /* little helper macro for BLI_uniquename */
224 #ifndef GIVE_STRADDR
225         #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
226 #endif
227
228 /* Generic function to set a unique name. It is only designed to be used in situations
229  * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
230  * 
231  * For places where this is used, see constraint.c for example...
232  *
233  *      name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
234  *      len: maximum length of string (to prevent overflows, etc.)
235  *      defname: the name that should be used by default if none is specified already
236  *      delim: the character which acts as a delimeter between parts of the name
237  */
238 static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
239 {
240         Link *link;
241
242         for (link = list->first; link; link= link->next) {
243                 if (link != vlink) {
244                         if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
245                                 return 1;
246                         }
247                 }
248         }
249
250         return 0;
251 }
252
253 static int uniquename_unique_check(void *arg, const char *name)
254 {
255         struct {ListBase *lb; void *vlink; short name_offs;} *data= arg;
256         return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
257 }
258
259 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len)
260 {
261         struct {ListBase *lb; void *vlink; short name_offs;} data;
262         data.lb= list;
263         data.vlink= vlink;
264         data.name_offs= name_offs;
265
266         assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
267
268         /* See if we are given an empty string */
269         if (ELEM(NULL, vlink, defname))
270                 return;
271
272         BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
273 }
274
275
276
277 /* ******************** string encoding ***************** */
278
279 /* This is quite an ugly function... its purpose is to
280  * take the dir name, make it absolute, and clean it up, replacing
281  * excess file entry stuff (like /tmp/../tmp/../)
282  * note that dir isn't protected for max string names... 
283  * 
284  * If relbase is NULL then its ignored
285  */
286
287 void BLI_cleanup_dir(const char *relabase, char *dir)
288 {
289         BLI_cleanup_file(relabase, dir);
290         BLI_add_slash(dir);
291
292 }
293
294 void BLI_cleanup_file(const char *relabase, char *dir)
295 {
296         short a;
297         char *start, *eind;
298         if (relabase) {
299                 BLI_path_abs(dir, relabase);
300         } else {
301                 if (dir[0]=='/' && dir[1]=='/') {
302                         if (dir[2]== '\0') {
303                                 return; /* path is "//" - cant clean it */
304                         }
305                         dir = dir+2; /* skip the first // */
306                 }
307         }
308         
309         /* Note
310          *   memmove( start, eind, strlen(eind)+1 );
311          * is the same as
312          *   strcpy( start, eind ); 
313          * except strcpy should not be used because there is overlap,
314           * so use memmove's slightly more obscure syntax - Campbell
315          */
316         
317 #ifdef WIN32
318         
319         /* Note, this should really be moved to the file selector,
320          * since this function is used in many areas */
321         if(strcmp(dir, ".")==0) {       /* happens for example in FILE_MAIN */
322            get_default_root(dir);
323            return;
324         }       
325
326         while ( (start = strstr(dir, "\\..\\")) ) {
327                 eind = start + strlen("\\..\\") - 1;
328                 a = start-dir-1;
329                 while (a>0) {
330                         if (dir[a] == '\\') break;
331                         a--;
332                 }
333                 if (a<0) {
334                         break;
335                 } else {
336                         memmove( dir+a, eind, strlen(eind)+1 );
337                 }
338         }
339
340         while ( (start = strstr(dir,"\\.\\")) ){
341                 eind = start + strlen("\\.\\") - 1;
342                 memmove( start, eind, strlen(eind)+1 );
343         }
344
345         while ( (start = strstr(dir,"\\\\" )) ){
346                 eind = start + strlen("\\\\") - 1;
347                 memmove( start, eind, strlen(eind)+1 );
348         }
349
350         if((a = strlen(dir))){                          /* remove the '\\' at the end */
351                 while(a>0 && dir[a-1] == '\\'){
352                         a--;
353                         dir[a] = 0;
354                 }
355         }
356 #else
357         if(dir[0]=='.') {       /* happens, for example in FILE_MAIN */
358            dir[0]= '/';
359            dir[1]= 0;
360            return;
361         }
362
363         /* support for odd paths: eg /../home/me --> /home/me
364          * this is a valid path in blender but we cant handle this the useual way below
365          * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */
366         while((strncmp(dir, "/../", 4)==0)) {
367                 memmove( dir, dir + 4, strlen(dir + 4) + 1 );
368         }
369
370         while ( (start = strstr(dir, "/../")) ) {
371                 eind = start + (4 - 1) /* strlen("/../") - 1 */;
372                 a = start-dir-1;
373                 while (a>0) {
374                         if (dir[a] == '/') break;
375                         a--;
376                 }
377                 if (a<0) {
378                         break;
379                 } else {
380                         memmove( dir+a, eind, strlen(eind)+1 );
381                 }
382         }
383
384         while ( (start = strstr(dir,"/./")) ){
385                 eind = start + (3 - 1) /* strlen("/./") - 1 */;
386                 memmove( start, eind, strlen(eind)+1 );
387         }
388
389         while ( (start = strstr(dir,"//" )) ){
390                 eind = start + (2 - 1) /* strlen("//") - 1 */;
391                 memmove( start, eind, strlen(eind)+1 );
392         }
393
394         if( (a = strlen(dir)) ){                                /* remove all '/' at the end */
395                 while(dir[a-1] == '/'){
396                         a--;
397                         dir[a] = 0;
398                         if (a<=0) break;
399                 }
400         }
401 #endif
402 }
403
404
405 void BLI_path_rel(char *file, const char *relfile)
406 {
407         char * lslash;
408         char temp[FILE_MAXDIR+FILE_MAXFILE];
409         char res[FILE_MAXDIR+FILE_MAXFILE];
410         
411         /* if file is already relative, bail out */
412         if(file[0]=='/' && file[1]=='/') return;
413         
414         /* also bail out if relative path is not set */
415         if (relfile[0] == 0) return;
416
417 #ifdef WIN32 
418         if (strlen(relfile) > 2 && relfile[1] != ':') {
419                 char* ptemp;
420                 /* fix missing volume name in relative base,
421                    can happen with old recent-files.txt files */
422                 get_default_root(temp);
423                 ptemp = &temp[2];
424                 if (relfile[0] != '\\' && relfile[0] != '/') {
425                         ptemp++;
426                 }
427                 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
428         } else {
429                 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
430         }
431
432         if (strlen(file) > 2) {
433                 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
434                         return;
435         }
436 #else
437         BLI_strncpy(temp, relfile, FILE_MAX);
438 #endif
439
440         BLI_char_switch(temp, '\\', '/');
441         BLI_char_switch(file, '\\', '/');
442         
443         /* remove /./ which confuse the following slash counting... */
444         BLI_cleanup_file(NULL, file);
445         BLI_cleanup_file(NULL, temp);
446         
447         /* the last slash in the file indicates where the path part ends */
448         lslash = BLI_last_slash(temp);
449
450         if (lslash) 
451         {       
452                 /* find the prefix of the filename that is equal for both filenames.
453                    This is replaced by the two slashes at the beginning */
454                 char *p= temp;
455                 char *q= file;
456
457                 while ((*p == *q)) {
458                         ++p; ++q;
459                         /* dont search beyond the end of the string
460                          * in the rare case they match */
461                         if ((*p=='\0') || (*q=='\0')) {
462                                 break;
463                         }
464                 }
465
466                 /* we might have passed the slash when the beginning of a dir matches 
467                    so we rewind. Only check on the actual filename
468                 */
469                 if (*q != '/') {
470                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
471                 } 
472                 else if (*p != '/') {
473                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
474                 }
475                 
476                 strcpy(res,     "//");
477
478                 /* p now points to the slash that is at the beginning of the part
479                    where the path is different from the relative path. 
480                    We count the number of directories we need to go up in the
481                    hierarchy to arrive at the common 'prefix' of the path
482                 */                      
483                 while (p && p < lslash) {
484                         if (*p == '/') 
485                                 strcat(res,     "../");
486                         ++p;
487                 }
488
489                 strcat(res, q+1); /* don't copy the slash at the beginning */
490                 
491 #ifdef  WIN32
492                 BLI_char_switch(res+2, '/', '\\');
493 #endif
494                 strcpy(file, res);
495         }
496 }
497
498 int BLI_has_parent(char *path)
499 {
500         int len;
501         int slashes = 0;
502         BLI_clean(path);
503         len = BLI_add_slash(path) - 1;
504
505         while (len>=0) {
506                 if ((path[len] == '\\') || (path[len] == '/'))
507                         slashes++;
508                 len--;
509         }
510         return slashes > 1;
511 }
512
513 int BLI_parent_dir(char *path)
514 {
515         static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
516         char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
517         BLI_strncpy(tmp, path, sizeof(tmp)-4);
518         BLI_add_slash(tmp);
519         strcat(tmp, parent_dir);
520         BLI_cleanup_dir(NULL, tmp);
521         
522         if (!BLI_testextensie(tmp, parent_dir)) {
523                 BLI_strncpy(path, tmp, sizeof(tmp));    
524                 return 1;
525         } else {
526                 return 0;
527         }
528 }
529
530 static int stringframe_chars(char *path, int *char_start, int *char_end)
531 {
532         int ch_sta, ch_end, i;
533         /* Insert current frame: file### -> file001 */
534         ch_sta = ch_end = 0;
535         for (i = 0; path[i] != '\0'; i++) {
536                 if (path[i] == '\\' || path[i] == '/') {
537                         ch_end = 0; /* this is a directory name, dont use any hashes we found */
538                 } else if (path[i] == '#') {
539                         ch_sta = i;
540                         ch_end = ch_sta+1;
541                         while (path[ch_end] == '#') {
542                                 ch_end++;
543                         }
544                         i = ch_end-1; /* keep searching */
545                         
546                         /* dont break, there may be a slash after this that invalidates the previous #'s */
547                 }
548         }
549
550         if(ch_end) {
551                 *char_start= ch_sta;
552                 *char_end= ch_end;
553                 return 1;
554         }
555         else {
556                 *char_start= -1;
557                 *char_end= -1;
558                 return 0;
559         }
560 }
561
562 static void ensure_digits(char *path, int digits)
563 {
564         char *file= BLI_last_slash(path);
565
566         if(file==NULL)
567                 file= path;
568
569         if(strrchr(file, '#') == NULL) {
570                 int len= strlen(file);
571
572                 while(digits--) {
573                         file[len++]= '#';
574                 }
575                 file[len]= '\0';
576         }
577 }
578
579 int BLI_path_frame(char *path, int frame, int digits)
580 {
581         int ch_sta, ch_end;
582
583         if(digits)
584                 ensure_digits(path, digits);
585
586         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
587                 char tmp[FILE_MAX];
588 #if 0   // neat but breaks on non ascii strings.
589                 char format[64];
590                 sprintf(format, "%%.%ds%%.%dd%%s", ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d%s" */
591                 sprintf(tmp, format, path, frame, path+ch_end);
592 #else
593                 char format[8];
594                 char *p;
595                 sprintf(format, "%%.%dd", ch_end-ch_sta); /* example result: "%.5d" */
596                 memcpy(tmp, path, sizeof(char) * ch_sta);
597                 p= tmp + ch_sta;
598                 p += sprintf(p, format, frame);
599                 memcpy(p, path + ch_end, strlen(path + ch_end));
600 #endif
601                 strcpy(path, tmp);
602                 return 1;
603         }
604         return 0;
605 }
606
607 int BLI_path_frame_range(char *path, int sta, int end, int digits)
608 {
609         int ch_sta, ch_end;
610
611         if(digits)
612                 ensure_digits(path, digits);
613
614         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
615                 char tmp[FILE_MAX], format[64];
616                 sprintf(format, "%%.%ds%%.%dd_%%.%dd%%s", ch_sta, ch_end-ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d-%.5d%s" */
617                 sprintf(tmp, format, path, sta, end, path+ch_end);
618                 strcpy(path, tmp);
619                 return 1;
620         }
621         return 0;
622 }
623
624 int BLI_path_abs(char *path, const char *basepath)
625 {
626         int wasrelative = (strncmp(path, "//", 2)==0);
627         char tmp[FILE_MAX];
628         char base[FILE_MAX];
629 #ifdef WIN32
630         char vol[3] = {'\0', '\0', '\0'};
631
632         BLI_strncpy(vol, path, 3);
633         /* we are checking here if we have an absolute path that is not in the current
634            blend file as a lib main - we are basically checking for the case that a 
635            UNIX root '/' is passed.
636         */
637         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
638                 char *p = path;
639                 get_default_root(tmp);
640                 // get rid of the slashes at the beginning of the path
641                 while (*p == '\\' || *p == '/') {
642                         p++;
643                 }
644                 strcat(tmp, p);
645         }
646         else {
647                 BLI_strncpy(tmp, path, FILE_MAX);
648         }
649 #else
650         BLI_strncpy(tmp, path, sizeof(tmp));
651         
652         /* Check for loading a windows path on a posix system
653          * in this case, there is no use in trying C:/ since it 
654          * will never exist on a unix os.
655          * 
656          * Add a / prefix and lowercase the driveletter, remove the :
657          * C:\foo.JPG -> /c/foo.JPG */
658         
659         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
660                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
661                 tmp[0] = '/'; 
662                 /* '\' the slash will be converted later */
663         }
664         
665 #endif
666
667         BLI_strncpy(base, basepath, sizeof(base));
668         
669         BLI_cleanup_file(NULL, base);
670         
671         /* push slashes into unix mode - strings entering this part are
672            potentially messed up: having both back- and forward slashes.
673            Here we push into one conform direction, and at the end we
674            push them into the system specific dir. This ensures uniformity
675            of paths and solving some problems (and prevent potential future
676            ones) -jesterKing. */
677         BLI_char_switch(tmp, '\\', '/');
678         BLI_char_switch(base, '\\', '/');       
679
680         /* Paths starting with // will get the blend file as their base,
681          * this isnt standard in any os but is uesed in blender all over the place */
682         if (wasrelative) {
683                 char *lslash= BLI_last_slash(base);
684                 if (lslash) {
685                         int baselen= (int) (lslash-base) + 1;
686                         /* use path for temp storage here, we copy back over it right away */
687                         BLI_strncpy(path, tmp+2, FILE_MAX);
688                         
689                         memcpy(tmp, base, baselen);
690                         BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
691                         BLI_strncpy(path, tmp, FILE_MAX);
692                 } else {
693                         BLI_strncpy(path, tmp+2, FILE_MAX);
694                 }
695         } else {
696                 BLI_strncpy(path, tmp, FILE_MAX);
697         }
698         
699         if (path[0]!='\0') {
700                 if ( path[strlen(path)-1]=='/') {
701                         /* remove the '/' so we avoid BLI_cleanup_dir adding an extra \ in WIN32 */
702                         path[strlen(path)-1] = '\0';
703                         BLI_cleanup_dir(NULL, path);
704                 } else {
705                         BLI_cleanup_file(NULL, path);
706                 }
707         }
708         
709 #ifdef WIN32
710         /* skip first two chars, which in case of
711            absolute path will be drive:/blabla and
712            in case of relpath //blabla/. So relpath
713            // will be retained, rest will be nice and
714            shiny win32 backward slashes :) -jesterKing
715         */
716         BLI_char_switch(path+2, '/', '\\');
717 #endif
718         
719         return wasrelative;
720 }
721
722
723 /*
724  * Should only be done with command line paths.
725  * this is NOT somthing blenders internal paths support like the // prefix
726  */
727 int BLI_path_cwd(char *path)
728 {
729         int wasrelative = 1;
730         int filelen = strlen(path);
731         
732 #ifdef WIN32
733         if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
734                 wasrelative = 0;
735 #else
736         if (filelen >= 2 && path[0] == '/')
737                 wasrelative = 0;
738 #endif
739         
740         if (wasrelative==1) {
741                 char cwd[FILE_MAXDIR + FILE_MAXFILE];
742                 BLI_getwdN(cwd); /* incase the full path to the blend isnt used */
743                 
744                 if (cwd[0] == '\0') {
745                         printf( "Could not get the current working directory - $PWD for an unknown reason.");
746                 } else {
747                         /* uses the blend path relative to cwd important for loading relative linked files.
748                         *
749                         * cwd should contain c:\ etc on win32 so the relbase can be NULL
750                         * relbase being NULL also prevents // being misunderstood as relative to the current
751                         * blend file which isnt a feature we want to use in this case since were dealing
752                         * with a path from the command line, rather then from inside Blender */
753                         
754                         char origpath[FILE_MAXDIR + FILE_MAXFILE];
755                         BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
756                         
757                         BLI_make_file_string(NULL, path, cwd, origpath); 
758                 }
759         }
760         
761         return wasrelative;
762 }
763
764
765 /* 'di's filename component is moved into 'fi', di is made a dir path */
766 void BLI_splitdirstring(char *di, char *fi)
767 {
768         char *lslash= BLI_last_slash(di);
769
770         if (lslash) {
771                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
772                 *(lslash+1)=0;
773         } else {
774                 BLI_strncpy(fi, di, FILE_MAXFILE);
775                 di[0]= 0;
776         }
777 }
778
779 void BLI_getlastdir(const char* dir, char *last, int maxlen)
780 {
781         const char *s = dir;
782         const char *lslash = NULL;
783         const char *prevslash = NULL;
784         while (*s) {
785                 if ((*s == '\\') || (*s == '/')) {
786                         prevslash = lslash;
787                         lslash = s;
788                 }
789                 s++;
790         }
791         if (prevslash) {
792                 BLI_strncpy(last, prevslash+1, maxlen);
793         } else {
794                 BLI_strncpy(last, dir, maxlen);
795         }
796 }
797
798 /* This is now only used to really get the user's default document folder */
799 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
800    as default location to save documents */
801 char *BLI_getDefaultDocumentFolder(void) {
802         #if !defined(WIN32)
803                 return getenv("HOME");
804
805         #else /* Windows */
806                 char * ret;
807                 static char documentfolder[MAXPATHLEN];
808                 HRESULT hResult;
809
810                 /* Check for %HOME% env var */
811
812                 ret = getenv("HOME");
813                 if(ret) {
814                         if (BLI_is_dir(ret)) return ret;
815                 }
816                                 
817                 /* add user profile support for WIN 2K / NT.
818                  * This is %APPDATA%, which translates to either
819                  * %USERPROFILE%\Application Data or since Vista
820                  * to %USERPROFILE%\AppData\Roaming
821                  */
822                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
823                 
824                 if (hResult == S_OK)
825                 {
826                         if (BLI_is_dir(documentfolder)) return documentfolder;
827                 }
828                 
829                 return NULL;
830         #endif
831 }
832
833 /* NEW stuff, to be cleaned up when fully migrated */
834 /* ************************************************************* */
835 /* ************************************************************* */
836
837 // #define PATH_DEBUG2
838
839 static char *blender_version_decimal(void)
840 {
841         static char version_str[5];
842         sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100);
843         return version_str;
844 }
845
846 static int test_path(char *targetpath, char *path_base, char *path_sep, char *folder_name)
847 {
848         char tmppath[FILE_MAX];
849         
850         if(path_sep)    BLI_join_dirfile(tmppath, path_base, path_sep);
851         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
852         
853         BLI_make_file_string("/", targetpath, tmppath, folder_name);
854         
855         if (BLI_is_dir(targetpath)) {
856 #ifdef PATH_DEBUG2
857                 printf("\tpath found: %s\n", targetpath);
858 #endif
859                 return 1;
860         }
861         else {
862 #ifdef PATH_DEBUG2
863                 printf("\tpath missing: %s\n", targetpath);
864 #endif
865                 //targetpath[0] = '\0';
866                 return 0;
867         }
868 }
869
870 static int test_env_path(char *path, char *envvar)
871 {
872         char *env = envvar?getenv(envvar):NULL;
873         if (!env) return 0;
874         
875         if (BLI_is_dir(env)) {
876                 BLI_strncpy(path, env, FILE_MAX);
877                 return 1;
878         } else {
879                 path[0] = '\0';
880                 return 0;
881         }
882 }
883
884 static int get_path_local(char *targetpath, char *folder_name, char *subfolder_name)
885 {
886         extern char bprogname[]; /* argv[0] from creator.c */
887         char bprogdir[FILE_MAX];
888         char relfolder[FILE_MAX];
889         
890 #ifdef PATH_DEBUG2
891         printf("get_path_local...\n");
892 #endif
893         
894         if (subfolder_name) {
895                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
896         } else {
897                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
898         }
899         
900         /* use argv[0] (bprogname) to get the path to the executable */
901         BLI_split_dirfile(bprogname, bprogdir, NULL);
902         
903         /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
904         if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder))
905                 return 1;
906
907         return 0;
908 }
909
910 static int get_path_user(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
911 {
912         char user_path[FILE_MAX];
913         const char *user_base_path;
914         
915         user_path[0] = '\0';
916
917         if (test_env_path(user_path, envvar)) {
918                 if (subfolder_name) {
919                         return test_path(targetpath, user_path, NULL, subfolder_name);
920                 } else {
921                         BLI_strncpy(targetpath, user_path, FILE_MAX);
922                         return 1;
923                 }
924         }
925
926         user_base_path = (const char *)GHOST_getUserDir();
927         if (user_base_path) {
928                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
929         }
930
931         if(!user_path[0])
932                 return 0;
933         
934 #ifdef PATH_DEBUG2
935         printf("get_path_user: %s\n", user_path);
936 #endif
937         
938         if (subfolder_name) {
939                 /* try $HOME/folder_name/subfolder_name */
940                 return test_path(targetpath, user_path, folder_name, subfolder_name);
941         } else {
942                 /* try $HOME/folder_name */
943                 return test_path(targetpath, user_path, NULL, folder_name);
944         }
945 }
946
947 static int get_path_system(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
948 {
949         char system_path[FILE_MAX];
950         const char *system_base_path;
951
952
953         /* first allow developer only overrides to the system path
954          * these are only used when running blender from source */
955         extern char bprogname[]; /* argv[0] from creator.c */
956         char cwd[FILE_MAX];
957         char relfolder[FILE_MAX];
958         char bprogdir[FILE_MAX];
959
960         /* use argv[0] (bprogname) to get the path to the executable */
961         BLI_split_dirfile(bprogname, bprogdir, NULL);
962
963         if (subfolder_name) {
964                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
965         } else {
966                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
967         }
968
969         /* try CWD/release/folder_name */
970         if(test_path(targetpath, BLI_getwdN(cwd), "release", relfolder))
971                 return 1;
972         
973         /* try EXECUTABLE_DIR/release/folder_name */
974         if(test_path(targetpath, bprogdir, "release", relfolder))
975                 return 1;
976         /* end developer overrides */
977
978
979
980         system_path[0] = '\0';
981
982         if (test_env_path(system_path, envvar)) {
983                 if (subfolder_name) {
984                         return test_path(targetpath, system_path, NULL, subfolder_name);
985                 } else {
986                         BLI_strncpy(targetpath, system_path, FILE_MAX);
987                         return 1;
988                 }
989         }
990
991         system_base_path = (const char *)GHOST_getSystemDir();
992         if (system_base_path) {
993                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
994         }
995         
996         if(!system_path[0])
997                 return 0;
998         
999 #ifdef PATH_DEBUG2
1000         printf("get_path_system: %s\n", system_path);
1001 #endif
1002         
1003         if (subfolder_name) {
1004                 /* try $BLENDERPATH/folder_name/subfolder_name */
1005                 return test_path(targetpath, system_path, folder_name, subfolder_name);
1006         } else {
1007                 /* try $BLENDERPATH/folder_name */
1008                 return test_path(targetpath, system_path, NULL, folder_name);
1009         }
1010 }
1011
1012 /* get a folder out of the 'folder_id' presets for paths */
1013 /* returns the path if found, NULL string if not */
1014 char *BLI_get_folder(int folder_id, char *subfolder)
1015 {
1016         static char path[FILE_MAX] = "";
1017         
1018         switch (folder_id) {
1019                 case BLENDER_DATAFILES:         /* general case */
1020                         if (get_path_local(path, "datafiles", subfolder)) break;
1021                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
1022                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
1023                         return NULL;
1024                         
1025                 case BLENDER_USER_DATAFILES:
1026                         if (get_path_local(path, "datafiles", subfolder)) break;
1027                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
1028                         return NULL;
1029                         
1030                 case BLENDER_SYSTEM_DATAFILES:
1031                         if (get_path_local(path, "datafiles", subfolder)) break;
1032                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES"))  break;
1033                         return NULL;
1034                         
1035                 case BLENDER_USER_AUTOSAVE:
1036                         if (get_path_local(path, "autosave", subfolder)) break;
1037                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES"))       break;
1038                         return NULL;
1039
1040                 case BLENDER_CONFIG:            /* general case */
1041                         if (get_path_local(path, "config", subfolder)) break;
1042                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1043                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1044                         return NULL;
1045                         
1046                 case BLENDER_USER_CONFIG:
1047                         if (get_path_local(path, "config", subfolder)) break;
1048                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1049                         return NULL;
1050                         
1051                 case BLENDER_SYSTEM_CONFIG:
1052                         if (get_path_local(path, "config", subfolder)) break;
1053                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1054                         return NULL;
1055                         
1056                 case BLENDER_SCRIPTS:           /* general case */
1057                         if (get_path_local(path, "scripts", subfolder)) break;
1058                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;           
1059                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1060                         return NULL;
1061                         
1062                 case BLENDER_USER_SCRIPTS:
1063                         if (get_path_local(path, "scripts", subfolder)) break;
1064                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1065                         return NULL;
1066                         
1067                 case BLENDER_SYSTEM_SCRIPTS:
1068                         if (get_path_local(path, "scripts", subfolder)) break;
1069                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1070                         return NULL;
1071                         
1072                 case BLENDER_PYTHON:            /* general case */
1073                         if (get_path_local(path, "python", subfolder)) break;
1074                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1075                         return NULL;
1076                         
1077                 case BLENDER_SYSTEM_PYTHON:
1078                         if (get_path_local(path, "python", subfolder)) break;
1079                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1080                         return NULL;
1081         }
1082         
1083         return path;
1084 }
1085
1086 char *BLI_get_user_folder_notest(int folder_id, char *subfolder)
1087 {
1088         static char path[FILE_MAX] = "";
1089
1090         switch (folder_id) {
1091                 case BLENDER_USER_DATAFILES:
1092                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES");
1093                         break;
1094                 case BLENDER_USER_CONFIG:
1095                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG");
1096                         break;
1097                 case BLENDER_USER_AUTOSAVE:
1098                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE");
1099                         break;
1100                 case BLENDER_USER_SCRIPTS:
1101                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS");
1102                         break;
1103         }
1104         if ('\0' == path[0]) {
1105                 return NULL;
1106         }
1107         return path;
1108 }
1109
1110 char *BLI_get_folder_create(int folder_id, char *subfolder)
1111 {
1112         char *path;
1113
1114         /* only for user folders */
1115         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1116                 return NULL;
1117         
1118         path = BLI_get_folder(folder_id, subfolder);
1119         
1120         if (!path) {
1121                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1122                 if (path) BLI_recurdir_fileops(path);
1123         }
1124         
1125         return path;
1126 }
1127
1128
1129 /* End new stuff */
1130 /* ************************************************************* */
1131 /* ************************************************************* */
1132
1133
1134
1135 #ifdef PATH_DEBUG
1136 #undef PATH_DEBUG
1137 #endif
1138
1139 void BLI_setenv(const char *env, const char*val)
1140 {
1141         /* SGI or free windows */
1142 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)))
1143         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1144
1145         sprintf(envstr, "%s=%s", env, val);
1146         putenv(envstr);
1147         MEM_freeN(envstr);
1148
1149         /* non-free windows */
1150 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1151         _putenv_s(env, val);
1152 #else
1153         /* linux/osx/bsd */
1154         setenv(env, val, 1);
1155 #endif
1156 }
1157
1158
1159 /**
1160  Only set an env var if already not there.
1161  Like Unix setenv(env, val, 0);
1162  */
1163 void BLI_setenv_if_new(const char *env, const char* val)
1164 {
1165         if(getenv(env) == NULL)
1166                 BLI_setenv(env, val);
1167 }
1168
1169
1170 void BLI_clean(char *path)
1171 {
1172         if(path==0) return;
1173 #ifdef WIN32
1174         if(path && strlen(path)>2) {
1175                 BLI_char_switch(path+2, '/', '\\');
1176         }
1177 #else
1178         BLI_char_switch(path, '\\', '/');
1179 #endif
1180 }
1181
1182 void BLI_char_switch(char *string, char from, char to) 
1183 {
1184         if(string==0) return;
1185         while (*string != 0) {
1186                 if (*string == from) *string = to;
1187                 string++;
1188         }
1189 }
1190
1191 void BLI_make_exist(char *dir) {
1192         int a;
1193
1194         BLI_char_switch(dir, ALTSEP, SEP);
1195
1196         a = strlen(dir);
1197
1198         while(BLI_is_dir(dir) == 0){
1199                 a --;
1200                 while(dir[a] != SEP){
1201                         a--;
1202                         if (a <= 0) break;
1203                 }
1204                 if (a >= 0) {
1205                         dir[a+1] = '\0';
1206                 }
1207                 else {
1208 #ifdef WIN32
1209                         get_default_root(dir);
1210 #else
1211                         strcpy(dir,"/");
1212 #endif
1213                         break;
1214                 }
1215         }
1216 }
1217
1218 void BLI_make_existing_file(char *name)
1219 {
1220         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1221
1222         BLI_strncpy(di, name, sizeof(di));
1223         BLI_splitdirstring(di, fi);
1224         
1225         /* test exist */
1226         if (BLI_exists(di) == 0) {
1227                 BLI_recurdir_fileops(di);
1228         }
1229 }
1230
1231
1232 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1233 {
1234         int sl;
1235
1236         if (!string || !dir || !file) return; /* We don't want any NULLs */
1237         
1238         string[0]= 0; /* ton */
1239
1240         /* we first push all slashes into unix mode, just to make sure we don't get
1241            any mess with slashes later on. -jesterKing */
1242         /* constant strings can be passed for those parameters - don't change them - elubie */
1243         /*
1244         BLI_char_switch(relabase, '\\', '/');
1245         BLI_char_switch(dir, '\\', '/');
1246         BLI_char_switch(file, '\\', '/');
1247         */
1248
1249         /* Resolve relative references */       
1250         if (relabase && dir[0] == '/' && dir[1] == '/') {
1251                 char *lslash;
1252                 
1253                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1254                 strcpy(string, relabase);
1255                 
1256                 lslash= BLI_last_slash(string);
1257                 if(lslash) *(lslash+1)= 0;
1258
1259                 dir+=2; /* Skip over the relative reference */
1260         }
1261 #ifdef WIN32
1262         else {
1263                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1264                         BLI_strncpy(string, dir, 3);
1265                         dir += 2;
1266                 }
1267                 else { /* no drive specified */
1268                         /* first option: get the drive from the relabase if it has one */
1269                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1270                                 BLI_strncpy(string, relabase, 3);       
1271                                 string[2] = '\\';
1272                                 string[3] = '\0';
1273                         }
1274                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1275                                 get_default_root(string);
1276                         }
1277                         
1278                         /* ignore leading slashes */
1279                         while (*dir == '/' || *dir == '\\') dir++;
1280                 }
1281         }
1282 #endif
1283
1284         strcat(string, dir);
1285
1286         /* Make sure string ends in one (and only one) slash */ 
1287         /* first trim all slashes from the end of the string */
1288         sl = strlen(string);
1289         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1290                 string[sl-1] = '\0';
1291                 sl--;
1292         }
1293         /* since we've now removed all slashes, put back one slash at the end. */
1294         strcat(string, "/");
1295         
1296         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1297                 file++;
1298                 
1299         strcat (string, file);
1300         
1301         /* Push all slashes to the system preferred direction */
1302         BLI_clean(string);
1303 }
1304
1305 int BLI_testextensie(const char *str, const char *ext)
1306 {
1307         short a, b;
1308         int retval;
1309
1310         a= strlen(str);
1311         b= strlen(ext);
1312
1313         if(a==0 || b==0 || b>=a) {
1314                 retval = 0;
1315         } else if (BLI_strcasecmp(ext, str + a - b)) {
1316                 retval = 0;     
1317         } else {
1318                 retval = 1;
1319         }
1320
1321         return (retval);
1322 }
1323
1324 int BLI_testextensie_array(const char *str, const char **ext_array)
1325 {
1326         int i=0;
1327         while(ext_array[i]) {
1328                 if(BLI_testextensie(str, ext_array[i])) {
1329                         return 1;
1330                 }
1331
1332                 i++;
1333         }
1334         return 0;
1335 }
1336
1337 /* semicolon separated wildcards, eg:
1338  *  '*.zip;*.py;*.exe' */
1339 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1340 {
1341         const char *ext_step= ext_fnmatch;
1342         char pattern[16];
1343
1344         while(ext_step[0]) {
1345                 char *ext_next;
1346                 int len_ext;
1347
1348                 if((ext_next=strchr(ext_step, ';'))) {
1349                         len_ext= (int)(ext_next - ext_step) + 1;
1350                 }
1351                 else {
1352                         len_ext= sizeof(pattern);
1353                 }
1354
1355                 BLI_strncpy(pattern, ext_step, len_ext);
1356
1357                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1358                         return 1;
1359                 }
1360                 ext_step += len_ext;
1361         }
1362
1363         return 0;
1364 }
1365
1366
1367 int BLI_replace_extension(char *path, int maxlen, const char *ext)
1368 {
1369         int a;
1370
1371         for(a=strlen(path)-1; a>=0; a--)
1372                 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1373                         break;
1374         
1375         if(path[a] != '.')
1376                 a= strlen(path);
1377
1378         if(a + strlen(ext) >= maxlen)
1379                 return 0;
1380
1381         strcpy(path+a, ext);
1382         return 1;
1383 }
1384
1385 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1386  * - wont change 'string'
1387  * - wont create any directories
1388  * - dosnt use CWD, or deal with relative paths.
1389  * - Only fill's in *dir and *file when they are non NULL
1390  * */
1391 void BLI_split_dirfile(const char *string, char *dir, char *file)
1392 {
1393         char *lslash_str = BLI_last_slash(string);
1394         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1395
1396         if (dir) {
1397                 if (lslash) {
1398                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1399                 } else {
1400                         dir[0] = '\0';
1401                 }
1402         }
1403         
1404         if (file) {
1405                 strcpy( file, string+lslash);
1406         }
1407 }
1408
1409 /* simple appending of filename to dir, does not check for valid path! */
1410 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1411 {
1412         int sl_dir;
1413         
1414         if(string != dir) /* compare pointers */
1415                 BLI_strncpy(string, dir, FILE_MAX);
1416
1417         if (!file)
1418                 return;
1419         
1420         sl_dir= BLI_add_slash(string);
1421         
1422         if (sl_dir <FILE_MAX) {
1423                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1424         }
1425 }
1426
1427 /* like pythons os.path.basename( ) */
1428 char *BLI_path_basename(char *path)
1429 {
1430         char *filename= BLI_last_slash(path);
1431         return filename ? filename + 1 : path;
1432 }
1433
1434 /*
1435   Produce image export path.
1436
1437   Fails returning 0 if image filename is empty or if destination path
1438   matches image path (i.e. both are the same file).
1439
1440   Trailing slash in dest_dir is optional.
1441
1442   Logic:
1443
1444   - if an image is "below" current .blend file directory, rebuild the
1445         same dir structure in dest_dir
1446
1447   For example //textures/foo/bar.png becomes
1448   [dest_dir]/textures/foo/bar.png.
1449
1450   - if an image is not "below" current .blend file directory,
1451   disregard it's path and copy it in the same directory where 3D file
1452   goes.
1453
1454   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1455
1456   This logic will help ensure that all image paths are relative and
1457   that a user gets his images in one place. It'll also provide
1458   consistent behaviour across exporters.
1459  */
1460 int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char *base_dir, const char *src_dir, const char *dest_dir)
1461 {
1462         char path[FILE_MAX];
1463         char dir[FILE_MAX];
1464         char base[FILE_MAX];
1465         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1466         char dest_path[FILE_MAX];
1467         char rel_dir[FILE_MAX];
1468         int len;
1469
1470         if (abs)
1471                 abs[0]= 0;
1472
1473         if (rel)
1474                 rel[0]= 0;
1475
1476         BLI_split_dirfile(base_dir, blend_dir, NULL);
1477
1478         if (src_dir[0]=='\0')
1479                 return 0;
1480
1481         BLI_strncpy(path, src_dir, sizeof(path));
1482
1483         /* expand "//" in filename and get absolute path */
1484         BLI_path_abs(path, base_dir);
1485
1486         /* get the directory part */
1487         BLI_split_dirfile(path, dir, base);
1488
1489         len= strlen(blend_dir);
1490
1491         rel_dir[0] = 0;
1492
1493         /* if image is "below" current .blend file directory */
1494         if (!strncmp(path, blend_dir, len)) {
1495
1496                 /* if image is _in_ current .blend file directory */
1497                 if (!strcmp(dir, blend_dir)) {
1498                         BLI_join_dirfile(dest_path, dest_dir, base);
1499                 }
1500                 /* "below" */
1501                 else {
1502                         /* rel = image_path_dir - blend_dir */
1503                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1504
1505                         BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1506                         BLI_join_dirfile(dest_path, dest_path, base);
1507                 }
1508
1509         }
1510         /* image is out of current directory */
1511         else {
1512                 BLI_join_dirfile(dest_path, dest_dir, base);
1513         }
1514
1515         if (abs)
1516                 BLI_strncpy(abs, dest_path, abs_size);
1517
1518         if (rel) {
1519                 strncat(rel, rel_dir, rel_size);
1520                 strncat(rel, base, rel_size);
1521         }
1522
1523         /* return 2 if src=dest */
1524         if (!strcmp(path, dest_path)) {
1525                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1526                 return 2;
1527         }
1528
1529         return 1;
1530 }
1531
1532 char *BLI_first_slash(char *string) {
1533         char *ffslash, *fbslash;
1534         
1535         ffslash= strchr(string, '/');   
1536         fbslash= strchr(string, '\\');
1537         
1538         if (!ffslash) return fbslash;
1539         else if (!fbslash) return ffslash;
1540         
1541         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1542         else return fbslash;
1543 }
1544
1545 char *BLI_last_slash(const char *string) {
1546         char *lfslash, *lbslash;
1547         
1548         lfslash= strrchr(string, '/');  
1549         lbslash= strrchr(string, '\\');
1550
1551         if (!lfslash) return lbslash; 
1552         else if (!lbslash) return lfslash;
1553         
1554         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1555         else return lfslash;
1556 }
1557
1558 /* adds a slash if there isnt one there already */
1559 int BLI_add_slash(char *string) {
1560         int len = strlen(string);
1561 #ifdef WIN32
1562         if (len==0 || string[len-1]!='\\') {
1563                 string[len] = '\\';
1564                 string[len+1] = '\0';
1565                 return len+1;
1566         }
1567 #else
1568         if (len==0 || string[len-1]!='/') {
1569                 string[len] = '/';
1570                 string[len+1] = '\0';
1571                 return len+1;
1572         }
1573 #endif
1574         return len;
1575 }
1576
1577 /* removes a slash if there is one */
1578 void BLI_del_slash(char *string) {
1579         int len = strlen(string);
1580         while (len) {
1581 #ifdef WIN32
1582                 if (string[len-1]=='\\') {
1583 #else
1584                 if (string[len-1]=='/') {
1585 #endif
1586                         string[len-1] = '\0';
1587                         len--;
1588                 } else {
1589                         break;
1590                 }
1591         }
1592 }
1593
1594 static int add_win32_extension(char *name)
1595 {
1596         int retval = 0;
1597         int type;
1598
1599         type = BLI_exist(name);
1600         if ((type == 0) || S_ISDIR(type)) {
1601 #ifdef _WIN32
1602                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1603                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1604                 char *extensions = getenv("PATHEXT");
1605                 if (extensions) {
1606                         char *temp;
1607                         do {
1608                                 strcpy(filename, name);
1609                                 temp = strstr(extensions, ";");
1610                                 if (temp) {
1611                                         strncpy(ext, extensions, temp - extensions);
1612                                         ext[temp - extensions] = 0;
1613                                         extensions = temp + 1;
1614                                         strcat(filename, ext);
1615                                 } else {
1616                                         strcat(filename, extensions);
1617                                 }
1618
1619                                 type = BLI_exist(filename);
1620                                 if (type && (! S_ISDIR(type))) {
1621                                         retval = 1;
1622                                         strcpy(name, filename);
1623                                         break;
1624                                 }
1625                         } while (temp);
1626                 }
1627 #endif
1628         } else {
1629                 retval = 1;
1630         }
1631
1632         return (retval);
1633 }
1634
1635 void BLI_where_am_i(char *fullname, const char *name)
1636 {
1637         char filename[FILE_MAXDIR+FILE_MAXFILE];
1638         char *path = NULL, *temp;
1639         
1640 #ifdef _WIN32
1641         char *separator = ";";
1642         char slash = '\\';
1643 #else
1644         char *separator = ":";
1645         char slash = '/';
1646 #endif
1647
1648         
1649 #ifdef __linux__
1650         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1651         path = br_find_exe( NULL );
1652         if (path) {
1653                 BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE);
1654                 free(path);
1655                 return;
1656         }
1657 #endif
1658
1659 #ifdef _WIN32
1660         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1661                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1662                 return;
1663         }
1664 #endif
1665
1666         /* unix and non linux */
1667         if (name && fullname && strlen(name)) {
1668                 strcpy(fullname, name);
1669                 if (name[0] == '.') {
1670                         // relative path, prepend cwd
1671                         BLI_getwdN(fullname);
1672                         
1673                         // not needed but avoids annoying /./ in name
1674                         if(name && name[0]=='.' && name[1]==slash)
1675                                 BLI_join_dirfile(fullname, fullname, name+2);
1676                         else
1677                                 BLI_join_dirfile(fullname, fullname, name);
1678                         
1679                         add_win32_extension(fullname);
1680                 } else if (BLI_last_slash(name)) {
1681                         // full path
1682                         strcpy(fullname, name);
1683                         add_win32_extension(fullname);
1684                 } else {
1685                         // search for binary in $PATH
1686                         path = getenv("PATH");
1687                         if (path) {
1688                                 do {
1689                                         temp = strstr(path, separator);
1690                                         if (temp) {
1691                                                 strncpy(filename, path, temp - path);
1692                                                 filename[temp - path] = 0;
1693                                                 path = temp + 1;
1694                                         } else {
1695                                                 strncpy(filename, path, sizeof(filename));
1696                                         }
1697                                         BLI_join_dirfile(fullname, fullname, name);
1698                                         if (add_win32_extension(filename)) {
1699                                                 strcpy(fullname, filename);
1700                                                 break;
1701                                         }
1702                                 } while (temp);
1703                         }
1704                 }
1705 #if defined(DEBUG)
1706                 if (strcmp(name, fullname)) {
1707                         printf("guessing '%s' == '%s'\n", name, fullname);
1708                 }
1709 #endif
1710
1711 #ifdef _WIN32
1712                 // in windows change long filename to short filename because
1713                 // win2k doesn't know how to parse a commandline with lots of
1714                 // spaces and double-quotes. There's another solution to this
1715                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1716                 // that's even uglier
1717                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1718 #if defined(DEBUG)
1719                 printf("Shortname = '%s'\n", fullname);
1720 #endif
1721 #endif
1722         }
1723 }
1724
1725 void BLI_where_is_temp(char *fullname, int usertemp)
1726 {
1727         fullname[0] = '\0';
1728         
1729         if (usertemp && BLI_is_dir(U.tempdir)) {
1730                 strcpy(fullname, U.tempdir);
1731         }
1732         
1733         
1734 #ifdef WIN32
1735         if (fullname[0] == '\0') {
1736                 char *tmp = getenv("TEMP"); /* Windows */
1737                 if (tmp && BLI_is_dir(tmp)) {
1738                         strcpy(fullname, tmp);
1739                 }
1740         }
1741 #else
1742         /* Other OS's - Try TMP and TMPDIR */
1743         if (fullname[0] == '\0') {
1744                 char *tmp = getenv("TMP");
1745                 if (tmp && BLI_is_dir(tmp)) {
1746                         strcpy(fullname, tmp);
1747                 }
1748         }
1749         
1750         if (fullname[0] == '\0') {
1751                 char *tmp = getenv("TMPDIR");
1752                 if (tmp && BLI_is_dir(tmp)) {
1753                         strcpy(fullname, tmp);
1754                 }
1755         }
1756 #endif  
1757         
1758         if (fullname[0] == '\0') {
1759                 strcpy(fullname, "/tmp/");
1760         } else {
1761                 /* add a trailing slash if needed */
1762                 BLI_add_slash(fullname);
1763 #ifdef WIN32
1764                 strcpy(U.tempdir, fullname); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1765 #endif
1766         }
1767 }
1768
1769 char *get_install_dir(void) {
1770         extern char bprogname[];
1771         char *tmpname = BLI_strdup(bprogname);
1772         char *cut;
1773
1774 #ifdef __APPLE__
1775         cut = strstr(tmpname, ".app");
1776         if (cut) cut[0] = 0;
1777 #endif
1778
1779         cut = BLI_last_slash(tmpname);
1780
1781         if (cut) {
1782                 cut[0] = 0;
1783                 return tmpname;
1784         } else {
1785                 MEM_freeN(tmpname);
1786                 return NULL;
1787         }
1788 }
1789
1790 #ifdef WITH_ICONV
1791
1792 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1793 {
1794         size_t inbytesleft=strlen(original);
1795         size_t outbytesleft=512;
1796         size_t rv=0;
1797         iconv_t cd;
1798         
1799         if (NULL == code) {
1800                 code = locale_charset();
1801         }
1802         cd=iconv_open("UTF-8", code);
1803
1804         if (cd == (iconv_t)(-1)) {
1805                 printf("iconv_open Error");
1806                 *utf_8='\0';
1807                 return ;
1808         }
1809         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1810         if (rv == (size_t) -1) {
1811                 printf("iconv Error\n");
1812                 return ;
1813         }
1814         *utf_8 = '\0';
1815         iconv_close(cd);
1816 }
1817 #endif // WITH_ICONV
1818
1819