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