Spelling Cleanup
[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 uesed 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 somthing 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         /*
1294         BLI_char_switch(relabase, '\\', '/');
1295         BLI_char_switch(dir, '\\', '/');
1296         BLI_char_switch(file, '\\', '/');
1297         */
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