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