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