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