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