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