style cleanup, brackets in else/if, some indentation.
[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                 /* find the prefix of the filename that is equal for both filenames.
473                  * This is replaced by the two slashes at the beginning */
474                 char *p= temp;
475                 char *q= file;
476
477 #ifdef WIN32
478                 while (tolower(*p) == tolower(*q))
479 #else
480                 while (*p == *q)
481 #endif
482                 {
483                         ++p; ++q;
484                         /* dont search beyond the end of the string
485                          * in the rare case they match */
486                         if ((*p=='\0') || (*q=='\0')) {
487                                 break;
488                         }
489                 }
490
491                 /* we might have passed the slash when the beginning of a dir matches 
492                  * so we rewind. Only check on the actual filename
493                  */
494                 if (*q != '/') {
495                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
496                 } 
497                 else if (*p != '/') {
498                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
499                 }
500                 
501                 strcpy(res,     "//");
502
503                 /* p now points to the slash that is at the beginning of the part
504                  * where the path is different from the relative path. 
505                  * We count the number of directories we need to go up in the
506                  * hierarchy to arrive at the common 'prefix' of the path
507                  */
508                 while (p && p < lslash) {
509                         if (*p == '/') 
510                                 strcat(res,     "../");
511                         ++p;
512                 }
513
514                 strcat(res, q+1); /* don't copy the slash at the beginning */
515                 
516 #ifdef  WIN32
517                 BLI_char_switch(res+2, '/', '\\');
518 #endif
519                 strcpy(file, res);
520         }
521 }
522
523 int BLI_has_parent(char *path)
524 {
525         int len;
526         int slashes = 0;
527         BLI_clean(path);
528         len = BLI_add_slash(path) - 1;
529
530         while (len>=0) {
531                 if ((path[len] == '\\') || (path[len] == '/'))
532                         slashes++;
533                 len--;
534         }
535         return slashes > 1;
536 }
537
538 int BLI_parent_dir(char *path)
539 {
540         static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
541         char tmp[FILE_MAX+4];
542         BLI_strncpy(tmp, path, sizeof(tmp)-4);
543         BLI_add_slash(tmp);
544         strcat(tmp, parent_dir);
545         BLI_cleanup_dir(NULL, tmp);
546
547         if (!BLI_testextensie(tmp, parent_dir)) {
548                 BLI_strncpy(path, tmp, sizeof(tmp));    
549                 return 1;
550         } else {
551                 return 0;
552         }
553 }
554
555 static int stringframe_chars(char *path, int *char_start, int *char_end)
556 {
557         int ch_sta, ch_end, i;
558         /* Insert current frame: file### -> file001 */
559         ch_sta = ch_end = 0;
560         for (i = 0; path[i] != '\0'; i++) {
561                 if (path[i] == '\\' || path[i] == '/') {
562                         ch_end = 0; /* this is a directory name, dont use any hashes we found */
563                 } else if (path[i] == '#') {
564                         ch_sta = i;
565                         ch_end = ch_sta+1;
566                         while (path[ch_end] == '#') {
567                                 ch_end++;
568                         }
569                         i = ch_end-1; /* keep searching */
570                         
571                         /* dont break, there may be a slash after this that invalidates the previous #'s */
572                 }
573         }
574
575         if(ch_end) {
576                 *char_start= ch_sta;
577                 *char_end= ch_end;
578                 return 1;
579         }
580         else {
581                 *char_start= -1;
582                 *char_end= -1;
583                 return 0;
584         }
585 }
586
587 static void ensure_digits(char *path, int digits)
588 {
589         char *file= BLI_last_slash(path);
590
591         if(file==NULL)
592                 file= path;
593
594         if(strrchr(file, '#') == NULL) {
595                 int len= strlen(file);
596
597                 while(digits--) {
598                         file[len++]= '#';
599                 }
600                 file[len]= '\0';
601         }
602 }
603
604 int BLI_path_frame(char *path, int frame, int digits)
605 {
606         int ch_sta, ch_end;
607
608         if(digits)
609                 ensure_digits(path, digits);
610
611         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
612                 char tmp[FILE_MAX];
613                 sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end-ch_sta, frame, path+ch_end);
614                 strcpy(path, tmp);
615                 return 1;
616         }
617         return 0;
618 }
619
620 int BLI_path_frame_range(char *path, int sta, int end, int digits)
621 {
622         int ch_sta, ch_end;
623
624         if(digits)
625                 ensure_digits(path, digits);
626
627         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
628                 char tmp[FILE_MAX];
629                 BLI_snprintf(tmp, sizeof(tmp),
630                              "%.*s%.*d-%.*d%s",
631                              ch_sta, path, ch_end-ch_sta, sta, ch_end-ch_sta, end, path+ch_end);
632                 BLI_strncpy(path, tmp, FILE_MAX);
633                 return 1;
634         }
635         return 0;
636 }
637
638 int BLI_path_abs(char *path, const char *basepath)
639 {
640         int wasrelative = (strncmp(path, "//", 2)==0);
641         char tmp[FILE_MAX];
642         char base[FILE_MAX];
643 #ifdef WIN32
644         char vol[3] = {'\0', '\0', '\0'};
645
646         BLI_strncpy(vol, path, 3);
647         /* we are checking here if we have an absolute path that is not in the current
648          * blend file as a lib main - we are basically checking for the case that a 
649          * UNIX root '/' is passed.
650          */
651         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
652                 char *p = path;
653                 get_default_root(tmp);
654                 // get rid of the slashes at the beginning of the path
655                 while (*p == '\\' || *p == '/') {
656                         p++;
657                 }
658                 strcat(tmp, p);
659         }
660         else {
661                 BLI_strncpy(tmp, path, FILE_MAX);
662         }
663 #else
664         BLI_strncpy(tmp, path, sizeof(tmp));
665         
666         /* Check for loading a windows path on a posix system
667          * in this case, there is no use in trying C:/ since it 
668          * will never exist on a unix os.
669          * 
670          * Add a / prefix and lowercase the driveletter, remove the :
671          * C:\foo.JPG -> /c/foo.JPG */
672         
673         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
674                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
675                 tmp[0] = '/'; 
676                 /* '\' the slash will be converted later */
677         }
678         
679 #endif
680
681         BLI_strncpy(base, basepath, sizeof(base));
682
683         /* file component is ignored, so dont bother with the trailing slash */
684         BLI_cleanup_path(NULL, base);
685         
686         /* push slashes into unix mode - strings entering this part are
687          * potentially messed up: having both back- and forward slashes.
688          * Here we push into one conform direction, and at the end we
689          * push them into the system specific dir. This ensures uniformity
690          * of paths and solving some problems (and prevent potential future
691          * ones) -jesterKing. */
692         BLI_char_switch(tmp, '\\', '/');
693         BLI_char_switch(base, '\\', '/');       
694
695         /* Paths starting with // will get the blend file as their base,
696          * this isnt standard in any os but is used in blender all over the place */
697         if (wasrelative) {
698                 char *lslash= BLI_last_slash(base);
699                 if (lslash) {
700                         int baselen= (int) (lslash-base) + 1;
701                         /* use path for temp storage here, we copy back over it right away */
702                         BLI_strncpy(path, tmp+2, FILE_MAX);
703                         
704                         memcpy(tmp, base, baselen);
705                         BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
706                         BLI_strncpy(path, tmp, FILE_MAX);
707                 } else {
708                         BLI_strncpy(path, tmp+2, FILE_MAX);
709                 }
710         } else {
711                 BLI_strncpy(path, tmp, FILE_MAX);
712         }
713
714         BLI_cleanup_path(NULL, path);
715
716 #ifdef WIN32
717         /* skip first two chars, which in case of
718          * absolute path will be drive:/blabla and
719          * in case of relpath //blabla/. So relpath
720          * // will be retained, rest will be nice and
721          * shiny win32 backward slashes :) -jesterKing
722          */
723         BLI_char_switch(path+2, '/', '\\');
724 #endif
725         
726         return wasrelative;
727 }
728
729
730 /*
731  * Should only be done with command line paths.
732  * this is NOT something blenders internal paths support like the // prefix
733  */
734 int BLI_path_cwd(char *path)
735 {
736         int wasrelative = 1;
737         int filelen = strlen(path);
738         
739 #ifdef WIN32
740         if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
741                 wasrelative = 0;
742 #else
743         if (filelen >= 2 && path[0] == '/')
744                 wasrelative = 0;
745 #endif
746         
747         if (wasrelative==1) {
748                 char cwd[FILE_MAX]= "";
749                 BLI_current_working_dir(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */
750                 
751                 if (cwd[0] == '\0') {
752                         printf( "Could not get the current working directory - $PWD for an unknown reason.");
753                 } else {
754                         /* uses the blend path relative to cwd important for loading relative linked files.
755                          *
756                          * cwd should contain c:\ etc on win32 so the relbase can be NULL
757                          * relbase being NULL also prevents // being misunderstood as relative to the current
758                          * blend file which isnt a feature we want to use in this case since were dealing
759                          * with a path from the command line, rather than from inside Blender */
760
761                         char origpath[FILE_MAX];
762                         BLI_strncpy(origpath, path, FILE_MAX);
763                         
764                         BLI_make_file_string(NULL, path, cwd, origpath); 
765                 }
766         }
767         
768         return wasrelative;
769 }
770
771
772 /* 'di's filename component is moved into 'fi', di is made a dir path */
773 void BLI_splitdirstring(char *di, char *fi)
774 {
775         char *lslash= BLI_last_slash(di);
776
777         if (lslash) {
778                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
779                 *(lslash+1)=0;
780         } else {
781                 BLI_strncpy(fi, di, FILE_MAXFILE);
782                 di[0]= 0;
783         }
784 }
785
786 void BLI_getlastdir(const char* dir, char *last, const size_t maxlen)
787 {
788         const char *s = dir;
789         const char *lslash = NULL;
790         const char *prevslash = NULL;
791         while (*s) {
792                 if ((*s == '\\') || (*s == '/')) {
793                         prevslash = lslash;
794                         lslash = s;
795                 }
796                 s++;
797         }
798         if (prevslash) {
799                 BLI_strncpy(last, prevslash+1, maxlen);
800         } else {
801                 BLI_strncpy(last, dir, maxlen);
802         }
803 }
804
805 /* This is now only used to really get the user's default document folder */
806 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
807  * as default location to save documents */
808 const char *BLI_getDefaultDocumentFolder(void)
809 {
810 #ifndef WIN32
811
812 #ifdef WITH_XDG_USER_DIRS
813                 const char *xdg_documents_dir= getenv("XDG_DOCUMENTS_DIR");
814                 if (xdg_documents_dir) {
815                         return xdg_documents_dir;
816                 }
817 #endif
818
819                 return getenv("HOME");
820
821 #else /* Windows */
822                 const char * ret;
823                 static char documentfolder[MAXPATHLEN];
824                 HRESULT hResult;
825
826                 /* Check for %HOME% env var */
827
828                 ret = getenv("HOME");
829                 if(ret) {
830                         if (BLI_is_dir(ret)) return ret;
831                 }
832                                 
833                 /* add user profile support for WIN 2K / NT.
834                  * This is %APPDATA%, which translates to either
835                  * %USERPROFILE%\Application Data or since Vista
836                  * to %USERPROFILE%\AppData\Roaming
837                  */
838                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
839                 
840                 if (hResult == S_OK) {
841                         if (BLI_is_dir(documentfolder)) return documentfolder;
842                 }
843                 
844                 return NULL;
845 #endif /* WIN32 */
846 }
847
848 /* NEW stuff, to be cleaned up when fully migrated */
849 /* ************************************************************* */
850 /* ************************************************************* */
851
852 // #define PATH_DEBUG2
853
854 static char *blender_version_decimal(const int ver)
855 {
856         static char version_str[5];
857         sprintf(version_str, "%d.%02d", ver/100, ver%100);
858         return version_str;
859 }
860
861 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
862 {
863         char tmppath[FILE_MAX];
864         
865         if(path_sep)    BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
866         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
867
868         /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
869         if(folder_name)
870                 BLI_make_file_string("/", targetpath, tmppath, folder_name);
871         else
872                 BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
873
874         if (BLI_is_dir(targetpath)) {
875 #ifdef PATH_DEBUG2
876                 printf("\tpath found: %s\n", targetpath);
877 #endif
878                 return 1;
879         }
880         else {
881 #ifdef PATH_DEBUG2
882                 printf("\tpath missing: %s\n", targetpath);
883 #endif
884                 //targetpath[0] = '\0';
885                 return 0;
886         }
887 }
888
889 static int test_env_path(char *path, const char *envvar)
890 {
891         const char *env = envvar?getenv(envvar):NULL;
892         if (!env) return 0;
893         
894         if (BLI_is_dir(env)) {
895                 BLI_strncpy(path, env, FILE_MAX);
896                 return 1;
897         } else {
898                 path[0] = '\0';
899                 return 0;
900         }
901 }
902
903 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
904 {
905         char relfolder[FILE_MAX];
906         
907 #ifdef PATH_DEBUG2
908         printf("get_path_local...\n");
909 #endif
910
911         if(folder_name) {
912                 if (subfolder_name) {
913                         BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
914                 } else {
915                         BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
916                 }
917         }
918         else {
919                 relfolder[0]= '\0';
920         }
921
922         /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
923         if(test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder))
924                 return 1;
925
926         return 0;
927 }
928
929 static int is_portable_install(void)
930 {
931         /* detect portable install by the existance of config folder */
932         const int ver= BLENDER_VERSION;
933         char path[FILE_MAX];
934
935         return get_path_local(path, "config", NULL, ver);
936 }
937
938 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
939 {
940         char user_path[FILE_MAX];
941         const char *user_base_path;
942
943         /* for portable install, user path is always local */
944         if (is_portable_install())
945                 return get_path_local(targetpath, folder_name, subfolder_name, ver);
946         
947         user_path[0] = '\0';
948
949         if (test_env_path(user_path, envvar)) {
950                 if (subfolder_name) {
951                         return test_path(targetpath, user_path, NULL, subfolder_name);
952                 } else {
953                         BLI_strncpy(targetpath, user_path, FILE_MAX);
954                         return 1;
955                 }
956         }
957
958         user_base_path = (const char *)GHOST_getUserDir();
959         if (user_base_path) {
960                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
961         }
962
963         if(!user_path[0])
964                 return 0;
965         
966 #ifdef PATH_DEBUG2
967         printf("get_path_user: %s\n", user_path);
968 #endif
969         
970         if (subfolder_name) {
971                 /* try $HOME/folder_name/subfolder_name */
972                 return test_path(targetpath, user_path, folder_name, subfolder_name);
973         } else {
974                 /* try $HOME/folder_name */
975                 return test_path(targetpath, user_path, NULL, folder_name);
976         }
977 }
978
979 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
980 {
981         char system_path[FILE_MAX];
982         const char *system_base_path;
983
984
985         /* first allow developer only overrides to the system path
986          * these are only used when running blender from source */
987         char cwd[FILE_MAX];
988         char relfolder[FILE_MAX];
989
990         if(folder_name) {
991                 if (subfolder_name) {
992                         BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
993                 } else {
994                         BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
995                 }
996         }
997         else {
998                 relfolder[0]= '\0';
999         }
1000
1001         /* try CWD/release/folder_name */
1002         if(BLI_current_working_dir(cwd, sizeof(cwd))) {
1003                 if(test_path(targetpath, cwd, "release", relfolder)) {
1004                         return 1;
1005                 }
1006         }
1007
1008         /* try EXECUTABLE_DIR/release/folder_name */
1009         if(test_path(targetpath, bprogdir, "release", relfolder))
1010                 return 1;
1011         /* end developer overrides */
1012
1013
1014
1015         system_path[0] = '\0';
1016
1017         if (test_env_path(system_path, envvar)) {
1018                 if (subfolder_name) {
1019                         return test_path(targetpath, system_path, NULL, subfolder_name);
1020                 } else {
1021                         BLI_strncpy(targetpath, system_path, FILE_MAX);
1022                         return 1;
1023                 }
1024         }
1025
1026         system_base_path = (const char *)GHOST_getSystemDir();
1027         if (system_base_path) {
1028                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
1029         }
1030         
1031         if(!system_path[0])
1032                 return 0;
1033         
1034 #ifdef PATH_DEBUG2
1035         printf("get_path_system: %s\n", system_path);
1036 #endif
1037         
1038         if (subfolder_name) {
1039                 /* try $BLENDERPATH/folder_name/subfolder_name */
1040                 return test_path(targetpath, system_path, folder_name, subfolder_name);
1041         } else {
1042                 /* try $BLENDERPATH/folder_name */
1043                 return test_path(targetpath, system_path, NULL, folder_name);
1044         }
1045 }
1046
1047 /* get a folder out of the 'folder_id' presets for paths */
1048 /* returns the path if found, NULL string if not */
1049 char *BLI_get_folder(int folder_id, const char *subfolder)
1050 {
1051         const int ver= BLENDER_VERSION;
1052         static char path[FILE_MAX] = "";
1053         
1054         switch (folder_id) {
1055                 case BLENDER_DATAFILES:         /* general case */
1056                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1057                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1058                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1059                         return NULL;
1060                         
1061                 case BLENDER_USER_DATAFILES:
1062                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1063                         return NULL;
1064                         
1065                 case BLENDER_SYSTEM_DATAFILES:
1066                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1067                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver))     break;
1068                         return NULL;
1069                         
1070                 case BLENDER_USER_AUTOSAVE:
1071                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver))  break;
1072                         return NULL;
1073
1074                 case BLENDER_USER_CONFIG:
1075                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
1076                         return NULL;
1077                         
1078                 case BLENDER_USER_SCRIPTS:
1079                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
1080                         return NULL;
1081                         
1082                 case BLENDER_SYSTEM_SCRIPTS:
1083                         if (get_path_local(path, "scripts", subfolder, ver)) break;
1084                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
1085                         return NULL;
1086                         
1087                 case BLENDER_SYSTEM_PYTHON:
1088                         if (get_path_local(path, "python", subfolder, ver)) break;
1089                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
1090                         return NULL;
1091         }
1092         
1093         return path;
1094 }
1095
1096 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1097 {
1098         const int ver= BLENDER_VERSION;
1099         static char path[FILE_MAX] = "";
1100
1101         switch (folder_id) {
1102                 case BLENDER_USER_DATAFILES:
1103                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
1104                         break;
1105                 case BLENDER_USER_CONFIG:
1106                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
1107                         break;
1108                 case BLENDER_USER_AUTOSAVE:
1109                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
1110                         break;
1111                 case BLENDER_USER_SCRIPTS:
1112                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
1113                         break;
1114         }
1115         if ('\0' == path[0]) {
1116                 return NULL;
1117         }
1118         return path;
1119 }
1120
1121 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1122 {
1123         char *path;
1124
1125         /* only for user folders */
1126         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1127                 return NULL;
1128         
1129         path = BLI_get_folder(folder_id, subfolder);
1130         
1131         if (!path) {
1132                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1133                 if (path) BLI_dir_create_recursive(path);
1134         }
1135         
1136         return path;
1137 }
1138
1139 char *BLI_get_folder_version(const int id, const int ver, const int do_check)
1140 {
1141         static char path[FILE_MAX] = "";
1142         int ok;
1143         switch(id) {
1144         case BLENDER_RESOURCE_PATH_USER:
1145                 ok= get_path_user(path, NULL, NULL, NULL, ver);
1146                 break;
1147         case BLENDER_RESOURCE_PATH_LOCAL:
1148                 ok= get_path_local(path, NULL, NULL, ver);
1149                 break;
1150         case BLENDER_RESOURCE_PATH_SYSTEM:
1151                 ok= get_path_system(path, NULL, NULL, NULL, ver);
1152                 break;
1153         default:
1154                 path[0]= '\0'; /* incase do_check is false */
1155                 ok= FALSE;
1156                 BLI_assert(!"incorrect ID");
1157         }
1158
1159         if((ok == FALSE) && do_check) {
1160                 return NULL;
1161         }
1162
1163         return path;
1164 }
1165
1166 /* End new stuff */
1167 /* ************************************************************* */
1168 /* ************************************************************* */
1169
1170
1171
1172 #ifdef PATH_DEBUG
1173 #undef PATH_DEBUG
1174 #endif
1175
1176 void BLI_setenv(const char *env, const char*val)
1177 {
1178         /* free windows */
1179 #if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
1180         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1181
1182         sprintf(envstr, "%s=%s", env, val);
1183         putenv(envstr);
1184         MEM_freeN(envstr);
1185
1186         /* non-free windows */
1187 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1188         _putenv_s(env, val);
1189 #else
1190         /* linux/osx/bsd */
1191         setenv(env, val, 1);
1192 #endif
1193 }
1194
1195
1196 /**
1197  * Only set an env var if already not there.
1198  * Like Unix setenv(env, val, 0);
1199  */
1200 void BLI_setenv_if_new(const char *env, const char* val)
1201 {
1202         if(getenv(env) == NULL)
1203                 BLI_setenv(env, val);
1204 }
1205
1206
1207 void BLI_clean(char *path)
1208 {
1209         if(path==NULL) return;
1210
1211 #ifdef WIN32
1212         if(path && BLI_strnlen(path, 3) > 2) {
1213                 BLI_char_switch(path+2, '/', '\\');
1214         }
1215 #else
1216         BLI_char_switch(path, '\\', '/');
1217 #endif
1218 }
1219
1220 void BLI_char_switch(char *string, char from, char to) 
1221 {
1222         if(string==NULL) return;
1223         while (*string != 0) {
1224                 if (*string == from) *string = to;
1225                 string++;
1226         }
1227 }
1228
1229 void BLI_make_exist(char *dir)
1230 {
1231         int a;
1232
1233         BLI_char_switch(dir, ALTSEP, SEP);
1234
1235         a = strlen(dir);
1236
1237         while (BLI_is_dir(dir) == 0) {
1238                 a --;
1239                 while (dir[a] != SEP) {
1240                         a--;
1241                         if (a <= 0) break;
1242                 }
1243                 if (a >= 0) {
1244                         dir[a+1] = '\0';
1245                 }
1246                 else {
1247 #ifdef WIN32
1248                         get_default_root(dir);
1249 #else
1250                         strcpy(dir,"/");
1251 #endif
1252                         break;
1253                 }
1254         }
1255 }
1256
1257 void BLI_make_existing_file(const char *name)
1258 {
1259         char di[FILE_MAX], fi[FILE_MAXFILE];
1260
1261         BLI_strncpy(di, name, sizeof(di));
1262         BLI_splitdirstring(di, fi);
1263         
1264         /* test exist */
1265         if (BLI_exists(di) == 0) {
1266                 BLI_dir_create_recursive(di);
1267         }
1268 }
1269
1270
1271 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1272 {
1273         int sl;
1274
1275         if (string) {
1276                 /* ensure this is always set even if dir/file are NULL */
1277                 string[0]= '\0';
1278
1279                 if (ELEM(NULL, dir, file)) {
1280                         return; /* We don't want any NULLs */
1281                 }
1282         }
1283         else {
1284                 return; /* string is NULL, probably shouldnt happen but return anyway */
1285         }
1286
1287
1288         /* we first push all slashes into unix mode, just to make sure we don't get
1289          * any mess with slashes later on. -jesterKing */
1290         /* constant strings can be passed for those parameters - don't change them - elubie */
1291 #if 0
1292         BLI_char_switch(relabase, '\\', '/');
1293         BLI_char_switch(dir, '\\', '/');
1294         BLI_char_switch(file, '\\', '/');
1295 #endif
1296
1297         /* Resolve relative references */       
1298         if (relabase && dir[0] == '/' && dir[1] == '/') {
1299                 char *lslash;
1300                 
1301                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1302                 strcpy(string, relabase);
1303                 
1304                 lslash= BLI_last_slash(string);
1305                 if(lslash) *(lslash+1)= 0;
1306
1307                 dir+=2; /* Skip over the relative reference */
1308         }
1309 #ifdef WIN32
1310         else {
1311                 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1312                         BLI_strncpy(string, dir, 3);
1313                         dir += 2;
1314                 }
1315                 else { /* no drive specified */
1316                         /* first option: get the drive from the relabase if it has one */
1317                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1318                                 BLI_strncpy(string, relabase, 3);       
1319                                 string[2] = '\\';
1320                                 string[3] = '\0';
1321                         }
1322                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1323                                 get_default_root(string);
1324                         }
1325                         
1326                         /* ignore leading slashes */
1327                         while (*dir == '/' || *dir == '\\') dir++;
1328                 }
1329         }
1330 #endif
1331
1332         strcat(string, dir);
1333
1334         /* Make sure string ends in one (and only one) slash */ 
1335         /* first trim all slashes from the end of the string */
1336         sl = strlen(string);
1337         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1338                 string[sl-1] = '\0';
1339                 sl--;
1340         }
1341         /* since we've now removed all slashes, put back one slash at the end. */
1342         strcat(string, "/");
1343         
1344         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1345                 file++;
1346                 
1347         strcat (string, file);
1348         
1349         /* Push all slashes to the system preferred direction */
1350         BLI_clean(string);
1351 }
1352
1353 int BLI_testextensie(const char *str, const char *ext)
1354 {
1355         short a, b;
1356         int retval;
1357         
1358         a= strlen(str);
1359         b= strlen(ext);
1360         
1361         if(a==0 || b==0 || b>=a) {
1362                 retval = 0;
1363         } else if (BLI_strcasecmp(ext, str + a - b)) {
1364                 retval = 0;     
1365         } else {
1366                 retval = 1;
1367         }
1368         
1369         return (retval);
1370 }
1371
1372 int BLI_testextensie_array(const char *str, const char **ext_array)
1373 {
1374         int i=0;
1375         while(ext_array[i]) {
1376                 if(BLI_testextensie(str, ext_array[i])) {
1377                         return 1;
1378                 }
1379
1380                 i++;
1381         }
1382         return 0;
1383 }
1384
1385 /* semicolon separated wildcards, eg:
1386  *  '*.zip;*.py;*.exe' */
1387 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1388 {
1389         const char *ext_step= ext_fnmatch;
1390         char pattern[16];
1391
1392         while(ext_step[0]) {
1393                 char *ext_next;
1394                 int len_ext;
1395
1396                 if((ext_next=strchr(ext_step, ';'))) {
1397                         len_ext= (int)(ext_next - ext_step) + 1;
1398                 }
1399                 else {
1400                         len_ext= sizeof(pattern);
1401                 }
1402
1403                 BLI_strncpy(pattern, ext_step, len_ext);
1404
1405                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1406                         return 1;
1407                 }
1408                 ext_step += len_ext;
1409         }
1410
1411         return 0;
1412 }
1413
1414
1415 int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1416 {
1417         size_t path_len= strlen(path);
1418         size_t ext_len= strlen(ext);
1419         ssize_t a;
1420
1421         for(a= path_len - 1; a >= 0; a--) {
1422                 if (ELEM3(path[a], '.', '/', '\\')) {
1423                         break;
1424                 }
1425         }
1426
1427         if ((a < 0) || (path[a] != '.')) {
1428                 a= path_len;
1429         }
1430
1431         if(a + ext_len >= maxlen)
1432                 return 0;
1433
1434         memcpy(path+a, ext, ext_len + 1);
1435         return 1;
1436 }
1437
1438 /* strip's trailing '.'s and adds the extension only when needed */
1439 int BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
1440 {
1441         size_t path_len= strlen(path);
1442         size_t ext_len= strlen(ext);
1443         ssize_t a;
1444
1445         /* first check the extension is alread there */
1446         if (    (ext_len <= path_len) &&
1447                 (strcmp(path + (path_len - ext_len), ext) == 0))
1448         {
1449                 return 1;
1450         }
1451
1452         for(a= path_len - 1; a >= 0; a--) {
1453                 if (path[a] == '.') {
1454                         path[a]= '\0';
1455                 }
1456                 else {
1457                         break;
1458                 }
1459         }
1460         a++;
1461
1462         if(a + ext_len >= maxlen)
1463                 return 0;
1464
1465         memcpy(path+a, ext, ext_len + 1);
1466         return 1;
1467 }
1468
1469 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1470  * - wont change 'string'
1471  * - wont create any directories
1472  * - dosnt use CWD, or deal with relative paths.
1473  * - Only fill's in *dir and *file when they are non NULL
1474  * */
1475 void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
1476 {
1477         char *lslash_str = BLI_last_slash(string);
1478         size_t lslash= lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
1479
1480         if (dir) {
1481                 if (lslash) {
1482                         BLI_strncpy( dir, string, MIN2(dirlen, lslash + 1)); /* +1 to include the slash and the last char */
1483                 }
1484                 else {
1485                         dir[0] = '\0';
1486                 }
1487         }
1488         
1489         if (file) {
1490                 BLI_strncpy(file, string+lslash, filelen);
1491         }
1492 }
1493
1494 void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen)
1495 {
1496         BLI_split_dirfile(string, dir, NULL, dirlen, 0);
1497 }
1498
1499 void BLI_split_file_part(const char *string, char *file, const size_t filelen)
1500 {
1501         BLI_split_dirfile(string, NULL, file, 0, filelen);
1502 }
1503
1504 /* simple appending of filename to dir, does not check for valid path! */
1505 void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
1506 {
1507         size_t dirlen= BLI_strnlen(dir, maxlen);
1508
1509         if (dst != dir) {
1510                 if(dirlen  == maxlen) {
1511                         memcpy(dst, dir, dirlen);
1512                         dst[dirlen - 1]= '\0';
1513                         return; /* dir fills the path */
1514                 }
1515                 else {
1516                         memcpy(dst, dir, dirlen + 1);
1517                 }
1518         }
1519
1520         if (dirlen + 1 >= maxlen) {
1521                 return; /* fills the path */
1522         }
1523
1524         /* inline BLI_add_slash */
1525         if (dst[dirlen - 1] != SEP) {
1526                 dst[dirlen++]= SEP;
1527                 dst[dirlen  ]= '\0';
1528         }
1529
1530         if (dirlen >= maxlen) {
1531                 return; /* fills the path */
1532         }
1533
1534         if (file == NULL) {
1535                 return;
1536         }
1537
1538         BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
1539 }
1540
1541 /* like pythons os.path.basename( ) */
1542 char *BLI_path_basename(char *path)
1543 {
1544         char *filename= BLI_last_slash(path);
1545         return filename ? filename + 1 : path;
1546 }
1547
1548 /**
1549  * Produce image export path.
1550  *
1551  * Fails returning 0 if image filename is empty or if destination path
1552  * matches image path (i.e. both are the same file).
1553  *
1554  * Trailing slash in dest_dir is optional.
1555  *
1556  * Logic:
1557  *
1558  * - if an image is "below" current .blend file directory, rebuild the
1559  * same dir structure in dest_dir
1560  *
1561  * For example //textures/foo/bar.png becomes
1562  * [dest_dir]/textures/foo/bar.png.
1563  *
1564  * - if an image is not "below" current .blend file directory,
1565  * disregard it's path and copy it in the same directory where 3D file
1566  * goes.
1567  *
1568  * For example //../foo/bar.png becomes [dest_dir]/bar.png.
1569  *
1570  * This logic will help ensure that all image paths are relative and
1571  * that a user gets his images in one place. It'll also provide
1572  * consistent behavior across exporters.
1573  */
1574 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)
1575 {
1576         char path[FILE_MAX];
1577         char dir[FILE_MAX];
1578         char base[FILE_MAX];
1579         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1580         char dest_path[FILE_MAX];
1581         char rel_dir[FILE_MAX];
1582         int len;
1583
1584         if (abs)
1585                 abs[0]= 0;
1586
1587         if (rel)
1588                 rel[0]= 0;
1589
1590         BLI_split_dir_part(base_dir, blend_dir, sizeof(blend_dir));
1591
1592         if (src_dir[0]=='\0')
1593                 return 0;
1594
1595         BLI_strncpy(path, src_dir, sizeof(path));
1596
1597         /* expand "//" in filename and get absolute path */
1598         BLI_path_abs(path, base_dir);
1599
1600         /* get the directory part */
1601         BLI_split_dirfile(path, dir, base, sizeof(dir), sizeof(base));
1602
1603         len= strlen(blend_dir);
1604
1605         rel_dir[0] = 0;
1606
1607         /* if image is "below" current .blend file directory */
1608         if (!strncmp(path, blend_dir, len)) {
1609
1610                 /* if image is _in_ current .blend file directory */
1611                 if (BLI_path_cmp(dir, blend_dir) == 0) {
1612                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1613                 }
1614                 /* "below" */
1615                 else {
1616                         /* rel = image_path_dir - blend_dir */
1617                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1618
1619                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
1620                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
1621                 }
1622
1623         }
1624         /* image is out of current directory */
1625         else {
1626                 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1627         }
1628
1629         if (abs)
1630                 BLI_strncpy(abs, dest_path, abs_len);
1631
1632         if (rel) {
1633                 strncat(rel, rel_dir, rel_len);
1634                 strncat(rel, base, rel_len);
1635         }
1636
1637         /* return 2 if src=dest */
1638         if (BLI_path_cmp(path, dest_path) == 0) {
1639                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1640                 return 2;
1641         }
1642
1643         return 1;
1644 }
1645
1646 char *BLI_first_slash(char *string)
1647 {
1648         char *ffslash, *fbslash;
1649         
1650         ffslash= strchr(string, '/');   
1651         fbslash= strchr(string, '\\');
1652         
1653         if (!ffslash) return fbslash;
1654         else if (!fbslash) return ffslash;
1655         
1656         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1657         else return fbslash;
1658 }
1659
1660 char *BLI_last_slash(const char *string)
1661 {
1662         char *lfslash, *lbslash;
1663         
1664         lfslash= strrchr(string, '/');  
1665         lbslash= strrchr(string, '\\');
1666
1667         if (!lfslash) return lbslash; 
1668         else if (!lbslash) return lfslash;
1669         
1670         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1671         else return lfslash;
1672 }
1673
1674 /* adds a slash if there isnt one there already */
1675 int BLI_add_slash(char *string)
1676 {
1677         int len = strlen(string);
1678         if (len==0 || string[len-1] != SEP) {
1679                 string[len] = SEP;
1680                 string[len+1] = '\0';
1681                 return len+1;
1682         }
1683         return len;
1684 }
1685
1686 /* removes a slash if there is one */
1687 void BLI_del_slash(char *string)
1688 {
1689         int len = strlen(string);
1690         while (len) {
1691                 if (string[len-1] == SEP) {
1692                         string[len-1] = '\0';
1693                         len--;
1694                 } else {
1695                         break;
1696                 }
1697         }
1698 }
1699
1700 static int add_win32_extension(char *name)
1701 {
1702         int retval = 0;
1703         int type;
1704
1705         type = BLI_exists(name);
1706         if ((type == 0) || S_ISDIR(type)) {
1707 #ifdef _WIN32
1708                 char filename[FILE_MAX];
1709                 char ext[FILE_MAX];
1710                 const char *extensions = getenv("PATHEXT");
1711                 if (extensions) {
1712                         char *temp;
1713                         do {
1714                                 strcpy(filename, name);
1715                                 temp = strstr(extensions, ";");
1716                                 if (temp) {
1717                                         strncpy(ext, extensions, temp - extensions);
1718                                         ext[temp - extensions] = 0;
1719                                         extensions = temp + 1;
1720                                         strcat(filename, ext);
1721                                 } else {
1722                                         strcat(filename, extensions);
1723                                 }
1724
1725                                 type = BLI_exists(filename);
1726                                 if (type && (! S_ISDIR(type))) {
1727                                         retval = 1;
1728                                         strcpy(name, filename);
1729                                         break;
1730                                 }
1731                         } while (temp);
1732                 }
1733 #endif
1734         } else {
1735                 retval = 1;
1736         }
1737
1738         return (retval);
1739 }
1740
1741 /**
1742  * Checks if name is a fully qualified filename to an executable.
1743  * If not it searches $PATH for the file. On Windows it also
1744  * adds the correct extension (.com .exe etc) from
1745  * $PATHEXT if necessary. Also on Windows it translates
1746  * the name to its 8.3 version to prevent problems with
1747  * spaces and stuff. Final result is returned in fullname.
1748  *
1749  * \param fullname The full path and full name of the executable
1750  * (must be FILE_MAX minimum)
1751  * \param name The name of the executable (usually argv[0]) to be checked
1752  */
1753 static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
1754 {
1755         char filename[FILE_MAX];
1756         const char *path = NULL, *temp;
1757
1758 #ifdef _WIN32
1759         const char *separator = ";";
1760 #else
1761         const char *separator = ":";
1762 #endif
1763
1764         
1765 #ifdef WITH_BINRELOC
1766         /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
1767         path = br_find_exe( NULL );
1768         if (path) {
1769                 BLI_strncpy(fullname, path, maxlen);
1770                 free((void *)path);
1771                 return;
1772         }
1773 #endif
1774
1775 #ifdef _WIN32
1776         if(GetModuleFileName(0, fullname, maxlen)) {
1777                 if(!BLI_exists(fullname)) {
1778                         printf("path can't be found: \"%.*s\"\n", maxlen, fullname);
1779                         MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
1780                 }
1781                 return;
1782         }
1783 #endif
1784
1785         /* unix and non linux */
1786         if (name && name[0]) {
1787                 BLI_strncpy(fullname, name, maxlen);
1788                 if (name[0] == '.') {
1789                         char wdir[FILE_MAX]= "";
1790                         BLI_current_working_dir(wdir, sizeof(wdir));     /* backup cwd to restore after */
1791
1792                         // not needed but avoids annoying /./ in name
1793                         if(name[1]==SEP)
1794                                 BLI_join_dirfile(fullname, maxlen, wdir, name+2);
1795                         else
1796                                 BLI_join_dirfile(fullname, maxlen, wdir, name);
1797
1798                         add_win32_extension(fullname); /* XXX, doesnt respect length */
1799                 }
1800                 else if (BLI_last_slash(name)) {
1801                         // full path
1802                         BLI_strncpy(fullname, name, maxlen);
1803                         add_win32_extension(fullname);
1804                 } else {
1805                         // search for binary in $PATH
1806                         path = getenv("PATH");
1807                         if (path) {
1808                                 do {
1809                                         temp = strstr(path, separator);
1810                                         if (temp) {
1811                                                 strncpy(filename, path, temp - path);
1812                                                 filename[temp - path] = 0;
1813                                                 path = temp + 1;
1814                                         } else {
1815                                                 strncpy(filename, path, sizeof(filename));
1816                                         }
1817                                         BLI_join_dirfile(fullname, maxlen, fullname, name);
1818                                         if (add_win32_extension(filename)) {
1819                                                 BLI_strncpy(fullname, filename, maxlen);
1820                                                 break;
1821                                         }
1822                                 } while (temp);
1823                         }
1824                 }
1825 #if defined(DEBUG)
1826                 if (strcmp(name, fullname)) {
1827                         printf("guessing '%s' == '%s'\n", name, fullname);
1828                 }
1829 #endif
1830         }
1831 }
1832
1833 void BLI_init_program_path(const char *argv0)
1834 {
1835         bli_where_am_i(bprogname, sizeof(bprogname), argv0);
1836         BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
1837 }
1838
1839 const char *BLI_program_path(void)
1840 {
1841         return bprogname;
1842 }
1843
1844 const char *BLI_program_dir(void)
1845 {
1846         return bprogdir;
1847 }
1848
1849 /**
1850  * Gets the temp directory when blender first runs.
1851  * If the default path is not found, use try $TEMP
1852  * 
1853  * Also make sure the temp dir has a trailing slash
1854  *
1855  * \param fullname The full path to the temp directory
1856  * \param maxlen The size of the fullname buffer
1857  * \param userdir Directory specified in user preferences 
1858  */
1859 static void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir)
1860 {
1861         fullname[0] = '\0';
1862         
1863         if (userdir && BLI_is_dir(userdir)) {
1864                 BLI_strncpy(fullname, userdir, maxlen);
1865         }
1866         
1867         
1868 #ifdef WIN32
1869         if (fullname[0] == '\0') {
1870                 const char *tmp = getenv("TEMP"); /* Windows */
1871                 if (tmp && BLI_is_dir(tmp)) {
1872                         BLI_strncpy(fullname, tmp, maxlen);
1873                 }
1874         }
1875 #else
1876         /* Other OS's - Try TMP and TMPDIR */
1877         if (fullname[0] == '\0') {
1878                 const char *tmp = getenv("TMP");
1879                 if (tmp && BLI_is_dir(tmp)) {
1880                         BLI_strncpy(fullname, tmp, maxlen);
1881                 }
1882         }
1883         
1884         if (fullname[0] == '\0') {
1885                 const char *tmp = getenv("TMPDIR");
1886                 if (tmp && BLI_is_dir(tmp)) {
1887                         BLI_strncpy(fullname, tmp, maxlen);
1888                 }
1889         }
1890 #endif  
1891         
1892         if (fullname[0] == '\0') {
1893                 BLI_strncpy(fullname, "/tmp/", maxlen);
1894         } else {
1895                 /* add a trailing slash if needed */
1896                 BLI_add_slash(fullname);
1897 #ifdef WIN32
1898                 if(userdir && userdir != fullname) {
1899                         BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1900                 }
1901 #endif
1902         }
1903 }
1904
1905 void BLI_init_temporary_dir(char *userdir)
1906 {
1907         BLI_where_is_temp(btempdir, FILE_MAX, userdir);
1908 }
1909
1910 const char *BLI_temporary_dir(void)
1911 {
1912         return btempdir;
1913 }
1914
1915 void BLI_system_temporary_dir(char *dir)
1916 {
1917         BLI_where_is_temp(dir, FILE_MAX, NULL);
1918 }
1919
1920 #ifdef WITH_ICONV
1921
1922 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1923 {
1924         size_t inbytesleft=strlen(original);
1925         size_t outbytesleft=512;
1926         size_t rv=0;
1927         iconv_t cd;
1928         
1929         if (NULL == code) {
1930                 code = locale_charset();
1931         }
1932         cd=iconv_open("UTF-8", code);
1933
1934         if (cd == (iconv_t)(-1)) {
1935                 printf("iconv_open Error");
1936                 *utf_8='\0';
1937                 return;
1938         }
1939         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1940         if (rv == (size_t) -1) {
1941                 printf("iconv Error\n");
1942                 return;
1943         }
1944         *utf_8 = '\0';
1945         iconv_close(cd);
1946 }
1947 #endif // WITH_ICONV
1948
1949