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