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