Merging r41937 through r42061 from trunk into soc-2011-tomato
[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
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         short 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 useual way below
382          * simply strip this prefix then evaluate the path as useual. 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_MAXDIR+FILE_MAXFILE];
430         char res[FILE_MAXDIR+FILE_MAXFILE];
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_MAXDIR + FILE_MAXFILE-3);
449         } else {
450                 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
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_MAXDIR+FILE_MAXFILE+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                 sprintf(tmp, "%.*s%.*d-%.*d%s", ch_sta, path, ch_end-ch_sta, sta, ch_end-ch_sta, end, path+ch_end);
631                 strcpy(path, tmp);
632                 return 1;
633         }
634         return 0;
635 }
636
637 int BLI_path_abs(char *path, const char *basepath)
638 {
639         int wasrelative = (strncmp(path, "//", 2)==0);
640         char tmp[FILE_MAX];
641         char base[FILE_MAX];
642 #ifdef WIN32
643         char vol[3] = {'\0', '\0', '\0'};
644
645         BLI_strncpy(vol, path, 3);
646         /* we are checking here if we have an absolute path that is not in the current
647            blend file as a lib main - we are basically checking for the case that a 
648            UNIX root '/' is passed.
649         */
650         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
651                 char *p = path;
652                 get_default_root(tmp);
653                 // get rid of the slashes at the beginning of the path
654                 while (*p == '\\' || *p == '/') {
655                         p++;
656                 }
657                 strcat(tmp, p);
658         }
659         else {
660                 BLI_strncpy(tmp, path, FILE_MAX);
661         }
662 #else
663         BLI_strncpy(tmp, path, sizeof(tmp));
664         
665         /* Check for loading a windows path on a posix system
666          * in this case, there is no use in trying C:/ since it 
667          * will never exist on a unix os.
668          * 
669          * Add a / prefix and lowercase the driveletter, remove the :
670          * C:\foo.JPG -> /c/foo.JPG */
671         
672         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
673                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
674                 tmp[0] = '/'; 
675                 /* '\' the slash will be converted later */
676         }
677         
678 #endif
679
680         BLI_strncpy(base, basepath, sizeof(base));
681
682         /* file component is ignored, so dont bother with the trailing slash */
683         BLI_cleanup_path(NULL, base);
684         
685         /* push slashes into unix mode - strings entering this part are
686            potentially messed up: having both back- and forward slashes.
687            Here we push into one conform direction, and at the end we
688            push them into the system specific dir. This ensures uniformity
689            of paths and solving some problems (and prevent potential future
690            ones) -jesterKing. */
691         BLI_char_switch(tmp, '\\', '/');
692         BLI_char_switch(base, '\\', '/');       
693
694         /* Paths starting with // will get the blend file as their base,
695          * this isnt standard in any os but is uesed in blender all over the place */
696         if (wasrelative) {
697                 char *lslash= BLI_last_slash(base);
698                 if (lslash) {
699                         int baselen= (int) (lslash-base) + 1;
700                         /* use path for temp storage here, we copy back over it right away */
701                         BLI_strncpy(path, tmp+2, FILE_MAX);
702                         
703                         memcpy(tmp, base, baselen);
704                         BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
705                         BLI_strncpy(path, tmp, FILE_MAX);
706                 } else {
707                         BLI_strncpy(path, tmp+2, FILE_MAX);
708                 }
709         } else {
710                 BLI_strncpy(path, tmp, FILE_MAX);
711         }
712
713         BLI_cleanup_path(NULL, path);
714
715 #ifdef WIN32
716         /* skip first two chars, which in case of
717            absolute path will be drive:/blabla and
718            in case of relpath //blabla/. So relpath
719            // will be retained, rest will be nice and
720            shiny win32 backward slashes :) -jesterKing
721         */
722         BLI_char_switch(path+2, '/', '\\');
723 #endif
724         
725         return wasrelative;
726 }
727
728
729 /*
730  * Should only be done with command line paths.
731  * this is NOT somthing blenders internal paths support like the // prefix
732  */
733 int BLI_path_cwd(char *path)
734 {
735         int wasrelative = 1;
736         int filelen = strlen(path);
737         
738 #ifdef WIN32
739         if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
740                 wasrelative = 0;
741 #else
742         if (filelen >= 2 && path[0] == '/')
743                 wasrelative = 0;
744 #endif
745         
746         if (wasrelative==1) {
747                 char cwd[FILE_MAXDIR + FILE_MAXFILE]= "";
748                 BLI_current_working_dir(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */
749                 
750                 if (cwd[0] == '\0') {
751                         printf( "Could not get the current working directory - $PWD for an unknown reason.");
752                 } else {
753                         /* uses the blend path relative to cwd important for loading relative linked files.
754                         *
755                         * cwd should contain c:\ etc on win32 so the relbase can be NULL
756                         * relbase being NULL also prevents // being misunderstood as relative to the current
757                         * blend file which isnt a feature we want to use in this case since were dealing
758                         * with a path from the command line, rather than from inside Blender */
759                         
760                         char origpath[FILE_MAXDIR + FILE_MAXFILE];
761                         BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
762                         
763                         BLI_make_file_string(NULL, path, cwd, origpath); 
764                 }
765         }
766         
767         return wasrelative;
768 }
769
770
771 /* 'di's filename component is moved into 'fi', di is made a dir path */
772 void BLI_splitdirstring(char *di, char *fi)
773 {
774         char *lslash= BLI_last_slash(di);
775
776         if (lslash) {
777                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
778                 *(lslash+1)=0;
779         } else {
780                 BLI_strncpy(fi, di, FILE_MAXFILE);
781                 di[0]= 0;
782         }
783 }
784
785 void BLI_getlastdir(const char* dir, char *last, const size_t maxlen)
786 {
787         const char *s = dir;
788         const char *lslash = NULL;
789         const char *prevslash = NULL;
790         while (*s) {
791                 if ((*s == '\\') || (*s == '/')) {
792                         prevslash = lslash;
793                         lslash = s;
794                 }
795                 s++;
796         }
797         if (prevslash) {
798                 BLI_strncpy(last, prevslash+1, maxlen);
799         } else {
800                 BLI_strncpy(last, dir, maxlen);
801         }
802 }
803
804 /* This is now only used to really get the user's default document folder */
805 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
806    as default location to save documents */
807 const char *BLI_getDefaultDocumentFolder(void)
808 {
809 #ifndef WIN32
810
811 #ifdef WITH_XDG_USER_DIRS
812                 const char *xdg_documents_dir= getenv("XDG_DOCUMENTS_DIR");
813                 if (xdg_documents_dir) {
814                         return xdg_documents_dir;
815                 }
816 #endif
817
818                 return getenv("HOME");
819
820 #else /* Windows */
821                 const char * ret;
822                 static char documentfolder[MAXPATHLEN];
823                 HRESULT hResult;
824
825                 /* Check for %HOME% env var */
826
827                 ret = getenv("HOME");
828                 if(ret) {
829                         if (BLI_is_dir(ret)) return ret;
830                 }
831                                 
832                 /* add user profile support for WIN 2K / NT.
833                  * This is %APPDATA%, which translates to either
834                  * %USERPROFILE%\Application Data or since Vista
835                  * to %USERPROFILE%\AppData\Roaming
836                  */
837                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
838                 
839                 if (hResult == S_OK)
840                 {
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_MAXDIR+FILE_MAXFILE], 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         /*
1292         BLI_char_switch(relabase, '\\', '/');
1293         BLI_char_switch(dir, '\\', '/');
1294         BLI_char_switch(file, '\\', '/');
1295         */
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         size_t a;
1420
1421         for(a= path_len - 1; a >= 0; a--) {
1422                 if (ELEM3(path[a], '.', '/', '\\')) {
1423                         break;
1424                 }
1425         }
1426
1427         if (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         size_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 behaviour 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_MAXDIR+FILE_MAXFILE];
1709                 char ext[FILE_MAXDIR+FILE_MAXFILE];
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_MAXDIR+FILE_MAXFILE];
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 userdir Directory specified in user preferences 
1857 */
1858 static void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir)
1859 {
1860         fullname[0] = '\0';
1861         
1862         if (userdir && BLI_is_dir(userdir)) {
1863                 BLI_strncpy(fullname, userdir, maxlen);
1864         }
1865         
1866         
1867 #ifdef WIN32
1868         if (fullname[0] == '\0') {
1869                 const char *tmp = getenv("TEMP"); /* Windows */
1870                 if (tmp && BLI_is_dir(tmp)) {
1871                         BLI_strncpy(fullname, tmp, maxlen);
1872                 }
1873         }
1874 #else
1875         /* Other OS's - Try TMP and TMPDIR */
1876         if (fullname[0] == '\0') {
1877                 const char *tmp = getenv("TMP");
1878                 if (tmp && BLI_is_dir(tmp)) {
1879                         BLI_strncpy(fullname, tmp, maxlen);
1880                 }
1881         }
1882         
1883         if (fullname[0] == '\0') {
1884                 const char *tmp = getenv("TMPDIR");
1885                 if (tmp && BLI_is_dir(tmp)) {
1886                         BLI_strncpy(fullname, tmp, maxlen);
1887                 }
1888         }
1889 #endif  
1890         
1891         if (fullname[0] == '\0') {
1892                 BLI_strncpy(fullname, "/tmp/", maxlen);
1893         } else {
1894                 /* add a trailing slash if needed */
1895                 BLI_add_slash(fullname);
1896 #ifdef WIN32
1897                 if(userdir && userdir != fullname) {
1898                         BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1899                 }
1900 #endif
1901         }
1902 }
1903
1904 void BLI_init_temporary_dir(char *userdir)
1905 {
1906         BLI_where_is_temp(btempdir, FILE_MAX, userdir);
1907 }
1908
1909 const char *BLI_temporary_dir(void)
1910 {
1911         return btempdir;
1912 }
1913
1914 void BLI_system_temporary_dir(char *dir)
1915 {
1916         BLI_where_is_temp(dir, FILE_MAX, NULL);
1917 }
1918
1919 #ifdef WITH_ICONV
1920
1921 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1922 {
1923         size_t inbytesleft=strlen(original);
1924         size_t outbytesleft=512;
1925         size_t rv=0;
1926         iconv_t cd;
1927         
1928         if (NULL == code) {
1929                 code = locale_charset();
1930         }
1931         cd=iconv_open("UTF-8", code);
1932
1933         if (cd == (iconv_t)(-1)) {
1934                 printf("iconv_open Error");
1935                 *utf_8='\0';
1936                 return ;
1937         }
1938         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1939         if (rv == (size_t) -1) {
1940                 printf("iconv Error\n");
1941                 return ;
1942         }
1943         *utf_8 = '\0';
1944         iconv_close(cd);
1945 }
1946 #endif // WITH_ICONV
1947
1948