remove $Id: tags after discussion on the mailign list: http://markmail.org/message...
[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 <assert.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "DNA_listBase.h"
43
44 #include "BLI_fileops.h"
45 #include "BLI_path_util.h"
46 #include "BLI_string.h"
47 #include "BLI_utildefines.h"
48
49 #include "BKE_utildefines.h"
50 #include "BKE_blender.h"        // BLENDER_VERSION
51
52 #include "GHOST_Path-api.h"
53
54 #if defined WIN32 && !defined _LIBC
55 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
56 #else
57 #  ifndef _GNU_SOURCE
58 #    define _GNU_SOURCE
59 #  endif
60 #  include <fnmatch.h>
61 #endif
62
63 #ifdef WIN32
64 #include <io.h>
65
66 #ifdef _WIN32_IE
67 #undef _WIN32_IE
68 #endif
69 #define _WIN32_IE 0x0501
70 #include <windows.h>
71 #include <shlobj.h>
72
73 #include "BLI_winstuff.h"
74
75 #else /* non windows */
76
77 #ifdef WITH_BINRELOC
78 #include "binreloc.h"
79 #endif
80
81 #endif /* WIN32 */
82
83 /* standard paths */
84 #ifdef WIN32
85 #define BLENDER_USER_FORMAT             "%s\\Blender Foundation\\Blender\\%s"
86 #define BLENDER_SYSTEM_FORMAT           "%s\\Blender Foundation\\Blender\\%s"
87 #elif defined(__APPLE__)
88 #define BLENDER_USER_FORMAT                     "%s/Blender/%s"
89 #define BLENDER_SYSTEM_FORMAT                   "%s/Blender/%s"
90 #else
91 #define BLENDER_USER_FORMAT                     "%s/.blender/%s"
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         short 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         #if !defined(WIN32)
801                 return getenv("HOME");
802
803         #else /* Windows */
804                 const char * ret;
805                 static char documentfolder[MAXPATHLEN];
806                 HRESULT hResult;
807
808                 /* Check for %HOME% env var */
809
810                 ret = getenv("HOME");
811                 if(ret) {
812                         if (BLI_is_dir(ret)) return ret;
813                 }
814                                 
815                 /* add user profile support for WIN 2K / NT.
816                  * This is %APPDATA%, which translates to either
817                  * %USERPROFILE%\Application Data or since Vista
818                  * to %USERPROFILE%\AppData\Roaming
819                  */
820                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
821                 
822                 if (hResult == S_OK)
823                 {
824                         if (BLI_is_dir(documentfolder)) return documentfolder;
825                 }
826                 
827                 return NULL;
828         #endif
829 }
830
831 /* NEW stuff, to be cleaned up when fully migrated */
832 /* ************************************************************* */
833 /* ************************************************************* */
834
835 // #define PATH_DEBUG2
836
837 static char *blender_version_decimal(const int ver)
838 {
839         static char version_str[5];
840         sprintf(version_str, "%d.%02d", ver/100, ver%100);
841         return version_str;
842 }
843
844 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
845 {
846         char tmppath[FILE_MAX];
847         
848         if(path_sep)    BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
849         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
850
851         /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
852         if(folder_name)
853                 BLI_make_file_string("/", targetpath, tmppath, folder_name);
854         else
855                 BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
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, const char *envvar)
873 {
874         const 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, const char *folder_name, const char *subfolder_name, const int ver)
887 {
888         char relfolder[FILE_MAX];
889         
890 #ifdef PATH_DEBUG2
891         printf("get_path_local...\n");
892 #endif
893
894         if(folder_name) {
895                 if (subfolder_name) {
896                         BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
897                 } else {
898                         BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
899                 }
900         }
901         else {
902                 relfolder[0]= '\0';
903         }
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(ver), relfolder))
907                 return 1;
908
909         return 0;
910 }
911
912 static int is_portable_install(void)
913 {
914         /* detect portable install by the existance of config folder */
915         const int ver= BLENDER_VERSION;
916         char path[FILE_MAX];
917
918         return get_path_local(path, "config", NULL, ver);
919 }
920
921 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
922 {
923         char user_path[FILE_MAX];
924         const char *user_base_path;
925
926         /* for portable install, user path is always local */
927         if (is_portable_install())
928                 return get_path_local(targetpath, folder_name, subfolder_name, ver);
929         
930         user_path[0] = '\0';
931
932         if (test_env_path(user_path, envvar)) {
933                 if (subfolder_name) {
934                         return test_path(targetpath, user_path, NULL, subfolder_name);
935                 } else {
936                         BLI_strncpy(targetpath, user_path, FILE_MAX);
937                         return 1;
938                 }
939         }
940
941         user_base_path = (const char *)GHOST_getUserDir();
942         if (user_base_path) {
943                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
944         }
945
946         if(!user_path[0])
947                 return 0;
948         
949 #ifdef PATH_DEBUG2
950         printf("get_path_user: %s\n", user_path);
951 #endif
952         
953         if (subfolder_name) {
954                 /* try $HOME/folder_name/subfolder_name */
955                 return test_path(targetpath, user_path, folder_name, subfolder_name);
956         } else {
957                 /* try $HOME/folder_name */
958                 return test_path(targetpath, user_path, NULL, folder_name);
959         }
960 }
961
962 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
963 {
964         char system_path[FILE_MAX];
965         const char *system_base_path;
966
967
968         /* first allow developer only overrides to the system path
969          * these are only used when running blender from source */
970         char cwd[FILE_MAX];
971         char relfolder[FILE_MAX];
972
973         if(folder_name) {
974                 if (subfolder_name) {
975                         BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
976                 } else {
977                         BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
978                 }
979         }
980         else {
981                 relfolder[0]= '\0';
982         }
983
984         /* try CWD/release/folder_name */
985         if(BLI_current_working_dir(cwd, sizeof(cwd))) {
986                 if(test_path(targetpath, cwd, "release", relfolder)) {
987                         return 1;
988                 }
989         }
990
991         /* try EXECUTABLE_DIR/release/folder_name */
992         if(test_path(targetpath, bprogdir, "release", relfolder))
993                 return 1;
994         /* end developer overrides */
995
996
997
998         system_path[0] = '\0';
999
1000         if (test_env_path(system_path, envvar)) {
1001                 if (subfolder_name) {
1002                         return test_path(targetpath, system_path, NULL, subfolder_name);
1003                 } else {
1004                         BLI_strncpy(targetpath, system_path, FILE_MAX);
1005                         return 1;
1006                 }
1007         }
1008
1009         system_base_path = (const char *)GHOST_getSystemDir();
1010         if (system_base_path) {
1011                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
1012         }
1013         
1014         if(!system_path[0])
1015                 return 0;
1016         
1017 #ifdef PATH_DEBUG2
1018         printf("get_path_system: %s\n", system_path);
1019 #endif
1020         
1021         if (subfolder_name) {
1022                 /* try $BLENDERPATH/folder_name/subfolder_name */
1023                 return test_path(targetpath, system_path, folder_name, subfolder_name);
1024         } else {
1025                 /* try $BLENDERPATH/folder_name */
1026                 return test_path(targetpath, system_path, NULL, folder_name);
1027         }
1028 }
1029
1030 /* get a folder out of the 'folder_id' presets for paths */
1031 /* returns the path if found, NULL string if not */
1032 char *BLI_get_folder(int folder_id, const char *subfolder)
1033 {
1034         const int ver= BLENDER_VERSION;
1035         static char path[FILE_MAX] = "";
1036         
1037         switch (folder_id) {
1038                 case BLENDER_DATAFILES:         /* general case */
1039                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1040                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1041                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1042                         return NULL;
1043                         
1044                 case BLENDER_USER_DATAFILES:
1045                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1046                         return NULL;
1047                         
1048                 case BLENDER_SYSTEM_DATAFILES:
1049                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1050                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver))     break;
1051                         return NULL;
1052                         
1053                 case BLENDER_USER_AUTOSAVE:
1054                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver))  break;
1055                         return NULL;
1056
1057                 case BLENDER_USER_CONFIG:
1058                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
1059                         return NULL;
1060                         
1061                 case BLENDER_USER_SCRIPTS:
1062                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
1063                         return NULL;
1064                         
1065                 case BLENDER_SYSTEM_SCRIPTS:
1066                         if (get_path_local(path, "scripts", subfolder, ver)) break;
1067                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
1068                         return NULL;
1069                         
1070                 case BLENDER_SYSTEM_PYTHON:
1071                         if (get_path_local(path, "python", subfolder, ver)) break;
1072                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
1073                         return NULL;
1074         }
1075         
1076         return path;
1077 }
1078
1079 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1080 {
1081         const int ver= BLENDER_VERSION;
1082         static char path[FILE_MAX] = "";
1083
1084         switch (folder_id) {
1085                 case BLENDER_USER_DATAFILES:
1086                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
1087                         break;
1088                 case BLENDER_USER_CONFIG:
1089                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
1090                         break;
1091                 case BLENDER_USER_AUTOSAVE:
1092                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
1093                         break;
1094                 case BLENDER_USER_SCRIPTS:
1095                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
1096                         break;
1097         }
1098         if ('\0' == path[0]) {
1099                 return NULL;
1100         }
1101         return path;
1102 }
1103
1104 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1105 {
1106         char *path;
1107
1108         /* only for user folders */
1109         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1110                 return NULL;
1111         
1112         path = BLI_get_folder(folder_id, subfolder);
1113         
1114         if (!path) {
1115                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1116                 if (path) BLI_dir_create_recursive(path);
1117         }
1118         
1119         return path;
1120 }
1121
1122 char *BLI_get_folder_version(const int id, const int ver, const int do_check)
1123 {
1124         static char path[FILE_MAX] = "";
1125         int ok;
1126         switch(id) {
1127         case BLENDER_RESOURCE_PATH_USER:
1128                 ok= get_path_user(path, NULL, NULL, NULL, ver);
1129                 break;
1130         case BLENDER_RESOURCE_PATH_LOCAL:
1131                 ok= get_path_local(path, NULL, NULL, ver);
1132                 break;
1133         case BLENDER_RESOURCE_PATH_SYSTEM:
1134                 ok= get_path_system(path, NULL, NULL, NULL, ver);
1135                 break;
1136         default:
1137                 path[0]= '\0'; /* incase do_check is false */
1138                 ok= FALSE;
1139                 BLI_assert(!"incorrect ID");
1140         }
1141
1142         if((ok == FALSE) && do_check) {
1143                 return NULL;
1144         }
1145
1146         return path;
1147 }
1148
1149 /* End new stuff */
1150 /* ************************************************************* */
1151 /* ************************************************************* */
1152
1153
1154
1155 #ifdef PATH_DEBUG
1156 #undef PATH_DEBUG
1157 #endif
1158
1159 void BLI_setenv(const char *env, const char*val)
1160 {
1161         /* free windows */
1162 #if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
1163         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1164
1165         sprintf(envstr, "%s=%s", env, val);
1166         putenv(envstr);
1167         MEM_freeN(envstr);
1168
1169         /* non-free windows */
1170 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1171         _putenv_s(env, val);
1172 #else
1173         /* linux/osx/bsd */
1174         setenv(env, val, 1);
1175 #endif
1176 }
1177
1178
1179 /**
1180  Only set an env var if already not there.
1181  Like Unix setenv(env, val, 0);
1182  */
1183 void BLI_setenv_if_new(const char *env, const char* val)
1184 {
1185         if(getenv(env) == NULL)
1186                 BLI_setenv(env, val);
1187 }
1188
1189
1190 void BLI_clean(char *path)
1191 {
1192         if(path==NULL) return;
1193
1194 #ifdef WIN32
1195         if(path && BLI_strnlen(path, 3) > 2) {
1196                 BLI_char_switch(path+2, '/', '\\');
1197         }
1198 #else
1199         BLI_char_switch(path, '\\', '/');
1200 #endif
1201 }
1202
1203 void BLI_char_switch(char *string, char from, char to) 
1204 {
1205         if(string==NULL) return;
1206         while (*string != 0) {
1207                 if (*string == from) *string = to;
1208                 string++;
1209         }
1210 }
1211
1212 void BLI_make_exist(char *dir)
1213 {
1214         int a;
1215
1216         BLI_char_switch(dir, ALTSEP, SEP);
1217
1218         a = strlen(dir);
1219
1220         while(BLI_is_dir(dir) == 0){
1221                 a --;
1222                 while(dir[a] != SEP){
1223                         a--;
1224                         if (a <= 0) break;
1225                 }
1226                 if (a >= 0) {
1227                         dir[a+1] = '\0';
1228                 }
1229                 else {
1230 #ifdef WIN32
1231                         get_default_root(dir);
1232 #else
1233                         strcpy(dir,"/");
1234 #endif
1235                         break;
1236                 }
1237         }
1238 }
1239
1240 void BLI_make_existing_file(const char *name)
1241 {
1242         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1243
1244         BLI_strncpy(di, name, sizeof(di));
1245         BLI_splitdirstring(di, fi);
1246         
1247         /* test exist */
1248         if (BLI_exists(di) == 0) {
1249                 BLI_dir_create_recursive(di);
1250         }
1251 }
1252
1253
1254 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1255 {
1256         int sl;
1257
1258         if (string) {
1259                 /* ensure this is always set even if dir/file are NULL */
1260                 string[0]= '\0';
1261
1262                 if (ELEM(NULL, dir, file)) {
1263                         return; /* We don't want any NULLs */
1264                 }
1265         }
1266         else {
1267                 return; /* string is NULL, probably shouldnt happen but return anyway */
1268         }
1269
1270
1271         /* we first push all slashes into unix mode, just to make sure we don't get
1272            any mess with slashes later on. -jesterKing */
1273         /* constant strings can be passed for those parameters - don't change them - elubie */
1274         /*
1275         BLI_char_switch(relabase, '\\', '/');
1276         BLI_char_switch(dir, '\\', '/');
1277         BLI_char_switch(file, '\\', '/');
1278         */
1279
1280         /* Resolve relative references */       
1281         if (relabase && dir[0] == '/' && dir[1] == '/') {
1282                 char *lslash;
1283                 
1284                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1285                 strcpy(string, relabase);
1286                 
1287                 lslash= BLI_last_slash(string);
1288                 if(lslash) *(lslash+1)= 0;
1289
1290                 dir+=2; /* Skip over the relative reference */
1291         }
1292 #ifdef WIN32
1293         else {
1294                 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1295                         BLI_strncpy(string, dir, 3);
1296                         dir += 2;
1297                 }
1298                 else { /* no drive specified */
1299                         /* first option: get the drive from the relabase if it has one */
1300                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1301                                 BLI_strncpy(string, relabase, 3);       
1302                                 string[2] = '\\';
1303                                 string[3] = '\0';
1304                         }
1305                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1306                                 get_default_root(string);
1307                         }
1308                         
1309                         /* ignore leading slashes */
1310                         while (*dir == '/' || *dir == '\\') dir++;
1311                 }
1312         }
1313 #endif
1314
1315         strcat(string, dir);
1316
1317         /* Make sure string ends in one (and only one) slash */ 
1318         /* first trim all slashes from the end of the string */
1319         sl = strlen(string);
1320         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1321                 string[sl-1] = '\0';
1322                 sl--;
1323         }
1324         /* since we've now removed all slashes, put back one slash at the end. */
1325         strcat(string, "/");
1326         
1327         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1328                 file++;
1329                 
1330         strcat (string, file);
1331         
1332         /* Push all slashes to the system preferred direction */
1333         BLI_clean(string);
1334 }
1335
1336 int BLI_testextensie(const char *str, const char *ext)
1337 {
1338         short a, b;
1339         int retval;
1340         
1341         a= strlen(str);
1342         b= strlen(ext);
1343         
1344         if(a==0 || b==0 || b>=a) {
1345                 retval = 0;
1346         } else if (BLI_strcasecmp(ext, str + a - b)) {
1347                 retval = 0;     
1348         } else {
1349                 retval = 1;
1350         }
1351         
1352         return (retval);
1353 }
1354
1355 int BLI_testextensie_array(const char *str, const char **ext_array)
1356 {
1357         int i=0;
1358         while(ext_array[i]) {
1359                 if(BLI_testextensie(str, ext_array[i])) {
1360                         return 1;
1361                 }
1362
1363                 i++;
1364         }
1365         return 0;
1366 }
1367
1368 /* semicolon separated wildcards, eg:
1369  *  '*.zip;*.py;*.exe' */
1370 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1371 {
1372         const char *ext_step= ext_fnmatch;
1373         char pattern[16];
1374
1375         while(ext_step[0]) {
1376                 char *ext_next;
1377                 int len_ext;
1378
1379                 if((ext_next=strchr(ext_step, ';'))) {
1380                         len_ext= (int)(ext_next - ext_step) + 1;
1381                 }
1382                 else {
1383                         len_ext= sizeof(pattern);
1384                 }
1385
1386                 BLI_strncpy(pattern, ext_step, len_ext);
1387
1388                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1389                         return 1;
1390                 }
1391                 ext_step += len_ext;
1392         }
1393
1394         return 0;
1395 }
1396
1397
1398 int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1399 {
1400         size_t a;
1401
1402         for(a=strlen(path); a>0; a--) {
1403                 if(path[a-1] == '.' || path[a-1] == '/' || path[a-1] == '\\') {
1404                         a--;
1405                         break;
1406                 }
1407         }
1408         
1409         if(path[a] != '.')
1410                 a= strlen(path);
1411
1412         if(a + strlen(ext) >= maxlen)
1413                 return 0;
1414
1415         strcpy(path+a, ext);
1416         return 1;
1417 }
1418
1419 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1420  * - wont change 'string'
1421  * - wont create any directories
1422  * - dosnt use CWD, or deal with relative paths.
1423  * - Only fill's in *dir and *file when they are non NULL
1424  * */
1425 void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
1426 {
1427         char *lslash_str = BLI_last_slash(string);
1428         size_t lslash= lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
1429
1430         if (dir) {
1431                 if (lslash) {
1432                         BLI_strncpy( dir, string, MIN2(dirlen, lslash + 1)); /* +1 to include the slash and the last char */
1433                 }
1434                 else {
1435                         dir[0] = '\0';
1436                 }
1437         }
1438         
1439         if (file) {
1440                 BLI_strncpy(file, string+lslash, filelen);
1441         }
1442 }
1443
1444 void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen)
1445 {
1446         BLI_split_dirfile(string, dir, NULL, dirlen, 0);
1447 }
1448
1449 void BLI_split_file_part(const char *string, char *file, const size_t filelen)
1450 {
1451         BLI_split_dirfile(string, NULL, file, 0, filelen);
1452 }
1453
1454 /* simple appending of filename to dir, does not check for valid path! */
1455 void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
1456 {
1457         size_t dirlen= BLI_strnlen(dir, maxlen);
1458
1459         if (dst != dir) {
1460                 if(dirlen  == maxlen) {
1461                         memcpy(dst, dir, dirlen);
1462                         dst[dirlen - 1]= '\0';
1463                         return; /* dir fills the path */
1464                 }
1465                 else {
1466                         memcpy(dst, dir, dirlen + 1);
1467                 }
1468         }
1469
1470         if (dirlen + 1 >= maxlen) {
1471                 return; /* fills the path */
1472         }
1473
1474         /* inline BLI_add_slash */
1475         if (dst[dirlen - 1] != SEP) {
1476                 dst[dirlen++]= SEP;
1477                 dst[dirlen  ]= '\0';
1478         }
1479
1480         if (dirlen >= maxlen) {
1481                 return; /* fills the path */
1482         }
1483
1484         if (file == NULL) {
1485                 return;
1486         }
1487
1488         BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
1489 }
1490
1491 /* like pythons os.path.basename( ) */
1492 char *BLI_path_basename(char *path)
1493 {
1494         char *filename= BLI_last_slash(path);
1495         return filename ? filename + 1 : path;
1496 }
1497
1498 /*
1499   Produce image export path.
1500
1501   Fails returning 0 if image filename is empty or if destination path
1502   matches image path (i.e. both are the same file).
1503
1504   Trailing slash in dest_dir is optional.
1505
1506   Logic:
1507
1508   - if an image is "below" current .blend file directory, rebuild the
1509         same dir structure in dest_dir
1510
1511   For example //textures/foo/bar.png becomes
1512   [dest_dir]/textures/foo/bar.png.
1513
1514   - if an image is not "below" current .blend file directory,
1515   disregard it's path and copy it in the same directory where 3D file
1516   goes.
1517
1518   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1519
1520   This logic will help ensure that all image paths are relative and
1521   that a user gets his images in one place. It'll also provide
1522   consistent behaviour across exporters.
1523  */
1524 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)
1525 {
1526         char path[FILE_MAX];
1527         char dir[FILE_MAX];
1528         char base[FILE_MAX];
1529         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1530         char dest_path[FILE_MAX];
1531         char rel_dir[FILE_MAX];
1532         int len;
1533
1534         if (abs)
1535                 abs[0]= 0;
1536
1537         if (rel)
1538                 rel[0]= 0;
1539
1540         BLI_split_dir_part(base_dir, blend_dir, sizeof(blend_dir));
1541
1542         if (src_dir[0]=='\0')
1543                 return 0;
1544
1545         BLI_strncpy(path, src_dir, sizeof(path));
1546
1547         /* expand "//" in filename and get absolute path */
1548         BLI_path_abs(path, base_dir);
1549
1550         /* get the directory part */
1551         BLI_split_dirfile(path, dir, base, sizeof(dir), sizeof(base));
1552
1553         len= strlen(blend_dir);
1554
1555         rel_dir[0] = 0;
1556
1557         /* if image is "below" current .blend file directory */
1558         if (!strncmp(path, blend_dir, len)) {
1559
1560                 /* if image is _in_ current .blend file directory */
1561                 if (BLI_path_cmp(dir, blend_dir) == 0) {
1562                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1563                 }
1564                 /* "below" */
1565                 else {
1566                         /* rel = image_path_dir - blend_dir */
1567                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1568
1569                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
1570                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
1571                 }
1572
1573         }
1574         /* image is out of current directory */
1575         else {
1576                 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1577         }
1578
1579         if (abs)
1580                 BLI_strncpy(abs, dest_path, abs_len);
1581
1582         if (rel) {
1583                 strncat(rel, rel_dir, rel_len);
1584                 strncat(rel, base, rel_len);
1585         }
1586
1587         /* return 2 if src=dest */
1588         if (BLI_path_cmp(path, dest_path) == 0) {
1589                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1590                 return 2;
1591         }
1592
1593         return 1;
1594 }
1595
1596 char *BLI_first_slash(char *string)
1597 {
1598         char *ffslash, *fbslash;
1599         
1600         ffslash= strchr(string, '/');   
1601         fbslash= strchr(string, '\\');
1602         
1603         if (!ffslash) return fbslash;
1604         else if (!fbslash) return ffslash;
1605         
1606         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1607         else return fbslash;
1608 }
1609
1610 char *BLI_last_slash(const char *string)
1611 {
1612         char *lfslash, *lbslash;
1613         
1614         lfslash= strrchr(string, '/');  
1615         lbslash= strrchr(string, '\\');
1616
1617         if (!lfslash) return lbslash; 
1618         else if (!lbslash) return lfslash;
1619         
1620         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1621         else return lfslash;
1622 }
1623
1624 /* adds a slash if there isnt one there already */
1625 int BLI_add_slash(char *string)
1626 {
1627         int len = strlen(string);
1628         if (len==0 || string[len-1] != SEP) {
1629                 string[len] = SEP;
1630                 string[len+1] = '\0';
1631                 return len+1;
1632         }
1633         return len;
1634 }
1635
1636 /* removes a slash if there is one */
1637 void BLI_del_slash(char *string)
1638 {
1639         int len = strlen(string);
1640         while (len) {
1641                 if (string[len-1] == SEP) {
1642                         string[len-1] = '\0';
1643                         len--;
1644                 } else {
1645                         break;
1646                 }
1647         }
1648 }
1649
1650 static int add_win32_extension(char *name)
1651 {
1652         int retval = 0;
1653         int type;
1654
1655         type = BLI_exists(name);
1656         if ((type == 0) || S_ISDIR(type)) {
1657 #ifdef _WIN32
1658                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1659                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1660                 const char *extensions = getenv("PATHEXT");
1661                 if (extensions) {
1662                         char *temp;
1663                         do {
1664                                 strcpy(filename, name);
1665                                 temp = strstr(extensions, ";");
1666                                 if (temp) {
1667                                         strncpy(ext, extensions, temp - extensions);
1668                                         ext[temp - extensions] = 0;
1669                                         extensions = temp + 1;
1670                                         strcat(filename, ext);
1671                                 } else {
1672                                         strcat(filename, extensions);
1673                                 }
1674
1675                                 type = BLI_exists(filename);
1676                                 if (type && (! S_ISDIR(type))) {
1677                                         retval = 1;
1678                                         strcpy(name, filename);
1679                                         break;
1680                                 }
1681                         } while (temp);
1682                 }
1683 #endif
1684         } else {
1685                 retval = 1;
1686         }
1687
1688         return (retval);
1689 }
1690
1691 /*
1692 * Checks if name is a fully qualified filename to an executable.
1693 * If not it searches $PATH for the file. On Windows it also
1694 * adds the correct extension (.com .exe etc) from
1695 * $PATHEXT if necessary. Also on Windows it translates
1696 * the name to its 8.3 version to prevent problems with
1697 * spaces and stuff. Final result is returned in fullname.
1698 *
1699 * @param fullname The full path and full name of the executable
1700 * (must be FILE_MAX minimum)
1701 * @param name The name of the executable (usually argv[0]) to be checked
1702 */
1703 static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
1704 {
1705         char filename[FILE_MAXDIR+FILE_MAXFILE];
1706         const char *path = NULL, *temp;
1707
1708 #ifdef _WIN32
1709         const char *separator = ";";
1710 #else
1711         const char *separator = ":";
1712 #endif
1713
1714         
1715 #ifdef WITH_BINRELOC
1716         /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
1717         path = br_find_exe( NULL );
1718         if (path) {
1719                 BLI_strncpy(fullname, path, maxlen);
1720                 free((void *)path);
1721                 return;
1722         }
1723 #endif
1724
1725 #ifdef _WIN32
1726         if(GetModuleFileName(0, fullname, maxlen)) {
1727                 if(!BLI_exists(fullname)) {
1728                         printf("path can't be found: \"%.*s\"\n", maxlen, fullname);
1729                         MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
1730                 }
1731                 return;
1732         }
1733 #endif
1734
1735         /* unix and non linux */
1736         if (name && name[0]) {
1737                 BLI_strncpy(fullname, name, maxlen);
1738                 if (name[0] == '.') {
1739                         char wdir[FILE_MAX]= "";
1740                         BLI_current_working_dir(wdir, sizeof(wdir));     /* backup cwd to restore after */
1741
1742                         // not needed but avoids annoying /./ in name
1743                         if(name[1]==SEP)
1744                                 BLI_join_dirfile(fullname, maxlen, wdir, name+2);
1745                         else
1746                                 BLI_join_dirfile(fullname, maxlen, wdir, name);
1747
1748                         add_win32_extension(fullname); /* XXX, doesnt respect length */
1749                 }
1750                 else if (BLI_last_slash(name)) {
1751                         // full path
1752                         BLI_strncpy(fullname, name, maxlen);
1753                         add_win32_extension(fullname);
1754                 } else {
1755                         // search for binary in $PATH
1756                         path = getenv("PATH");
1757                         if (path) {
1758                                 do {
1759                                         temp = strstr(path, separator);
1760                                         if (temp) {
1761                                                 strncpy(filename, path, temp - path);
1762                                                 filename[temp - path] = 0;
1763                                                 path = temp + 1;
1764                                         } else {
1765                                                 strncpy(filename, path, sizeof(filename));
1766                                         }
1767                                         BLI_join_dirfile(fullname, maxlen, fullname, name);
1768                                         if (add_win32_extension(filename)) {
1769                                                 BLI_strncpy(fullname, filename, maxlen);
1770                                                 break;
1771                                         }
1772                                 } while (temp);
1773                         }
1774                 }
1775 #if defined(DEBUG)
1776                 if (strcmp(name, fullname)) {
1777                         printf("guessing '%s' == '%s'\n", name, fullname);
1778                 }
1779 #endif
1780         }
1781 }
1782
1783 void BLI_init_program_path(const char *argv0)
1784 {
1785         bli_where_am_i(bprogname, sizeof(bprogname), argv0);
1786         BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
1787 }
1788
1789 const char *BLI_program_path(void)
1790 {
1791         return bprogname;
1792 }
1793
1794 const char *BLI_program_dir(void)
1795 {
1796         return bprogdir;
1797 }
1798
1799 /**
1800 * Gets the temp directory when blender first runs.
1801 * If the default path is not found, use try $TEMP
1802
1803 * Also make sure the temp dir has a trailing slash
1804 *
1805 * @param fullname The full path to the temp directory
1806 * @param userdir Directory specified in user preferences 
1807 */
1808 void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir)
1809 {
1810         fullname[0] = '\0';
1811         
1812         if (userdir && BLI_is_dir(userdir)) {
1813                 BLI_strncpy(fullname, userdir, maxlen);
1814         }
1815         
1816         
1817 #ifdef WIN32
1818         if (fullname[0] == '\0') {
1819                 const char *tmp = getenv("TEMP"); /* Windows */
1820                 if (tmp && BLI_is_dir(tmp)) {
1821                         BLI_strncpy(fullname, tmp, maxlen);
1822                 }
1823         }
1824 #else
1825         /* Other OS's - Try TMP and TMPDIR */
1826         if (fullname[0] == '\0') {
1827                 const char *tmp = getenv("TMP");
1828                 if (tmp && BLI_is_dir(tmp)) {
1829                         BLI_strncpy(fullname, tmp, maxlen);
1830                 }
1831         }
1832         
1833         if (fullname[0] == '\0') {
1834                 const char *tmp = getenv("TMPDIR");
1835                 if (tmp && BLI_is_dir(tmp)) {
1836                         BLI_strncpy(fullname, tmp, maxlen);
1837                 }
1838         }
1839 #endif  
1840         
1841         if (fullname[0] == '\0') {
1842                 BLI_strncpy(fullname, "/tmp/", maxlen);
1843         } else {
1844                 /* add a trailing slash if needed */
1845                 BLI_add_slash(fullname);
1846 #ifdef WIN32
1847                 if(userdir != fullname) {
1848                         BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1849                 }
1850 #endif
1851         }
1852 }
1853
1854 void BLI_init_temporary_dir(char *userdir)
1855 {
1856         BLI_where_is_temp(btempdir, FILE_MAX, userdir);
1857 }
1858
1859 const char *BLI_temporary_dir(void)
1860 {
1861         return btempdir;
1862 }
1863
1864 void BLI_system_temporary_dir(char *dir)
1865 {
1866         BLI_where_is_temp(dir, FILE_MAX, NULL);
1867 }
1868
1869 #ifdef WITH_ICONV
1870
1871 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1872 {
1873         size_t inbytesleft=strlen(original);
1874         size_t outbytesleft=512;
1875         size_t rv=0;
1876         iconv_t cd;
1877         
1878         if (NULL == code) {
1879                 code = locale_charset();
1880         }
1881         cd=iconv_open("UTF-8", code);
1882
1883         if (cd == (iconv_t)(-1)) {
1884                 printf("iconv_open Error");
1885                 *utf_8='\0';
1886                 return ;
1887         }
1888         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1889         if (rv == (size_t) -1) {
1890                 printf("iconv Error\n");
1891                 return ;
1892         }
1893         *utf_8 = '\0';
1894         iconv_close(cd);
1895 }
1896 #endif // WITH_ICONV
1897
1898