== installation paths ==
[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 recent-files.txt 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 /* NEW stuff, to be cleaned up when fully migrated */
799 /* ************************************************************* */
800 /* ************************************************************* */
801
802 // #define PATH_DEBUG2
803
804 static char *blender_version_decimal(void)
805 {
806         static char version_str[5];
807         sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100);
808         return version_str;
809 }
810
811 static int test_path(char *targetpath, char *path_base, char *path_sep, char *folder_name)
812 {
813         char tmppath[FILE_MAX];
814         
815         if(path_sep)    BLI_join_dirfile(tmppath, path_base, path_sep);
816         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
817         
818         BLI_make_file_string("/", targetpath, tmppath, folder_name);
819         
820         if (BLI_is_dir(targetpath)) {
821 #ifdef PATH_DEBUG2
822                 printf("\tpath found: %s\n", targetpath);
823 #endif
824                 return 1;
825         }
826         else {
827 #ifdef PATH_DEBUG2
828                 printf("\tpath missing: %s\n", targetpath);
829 #endif
830                 //targetpath[0] = '\0';
831                 return 0;
832         }
833 }
834
835 static int test_env_path(char *path, char *envvar)
836 {
837         char *env = envvar?getenv(envvar):NULL;
838         if (!env) return 0;
839         
840         if (BLI_is_dir(env)) {
841                 BLI_strncpy(path, env, FILE_MAX);
842                 return 1;
843         } else {
844                 path[0] = '\0';
845                 return 0;
846         }
847 }
848
849 static int get_path_local(char *targetpath, char *folder_name, char *subfolder_name)
850 {
851         extern char bprogname[]; /* argv[0] from creator.c */
852         char bprogdir[FILE_MAX];
853         char relfolder[FILE_MAX];
854         char cwd[FILE_MAX];
855         char *s;
856         int i;
857         
858 #ifdef PATH_DEBUG2
859         printf("get_path_local...\n");
860 #endif
861         
862         if (subfolder_name) {
863                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
864         } else {
865                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
866         }
867         
868         /* use argv[0] (bprogname) to get the path to the executable */
869         s = BLI_last_slash(bprogname);
870         i = s - bprogname + 1;
871         BLI_strncpy(bprogdir, bprogname, i);
872         
873         /* try EXECUTABLE_DIR/folder_name */
874         if(test_path(targetpath, bprogdir, "", relfolder))
875                 return 1;
876         
877         /* try CWD/release/folder_name */
878         if(test_path(targetpath, BLI_getwdN(cwd), "release", relfolder))
879                 return 1;
880         
881         /* try EXECUTABLE_DIR/release/folder_name */
882         if(test_path(targetpath, bprogdir, "release", relfolder))
883                 return 1;
884         
885         /* try EXECUTABLE_DIR/2.5/folder_name - new default directory for local blender installed files */
886         if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder))
887                 return 1;
888
889         /* try ./.blender/folder_name -- DEPRECATED, need to update build systems */
890         if(test_path(targetpath, bprogdir, ".blender", relfolder))
891                 return 1;
892
893         return 0;
894 }
895
896 static int get_path_user(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
897 {
898         char user_path[FILE_MAX];
899         const char *user_base_path;
900         
901         user_path[0] = '\0';
902
903         if (test_env_path(user_path, envvar)) {
904                 if (subfolder_name) {
905                         return test_path(targetpath, user_path, NULL, subfolder_name);
906                 } else {
907                         BLI_strncpy(targetpath, user_path, FILE_MAX);
908                         return 1;
909                 }
910         }
911
912         user_base_path = (const char *)GHOST_getUserDir();
913         if (user_base_path) {
914                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
915         }
916
917         if(!user_path[0])
918                 return 0;
919         
920 #ifdef PATH_DEBUG2
921         printf("get_path_user: %s\n", user_path);
922 #endif
923         
924         if (subfolder_name) {
925                 /* try $HOME/folder_name/subfolder_name */
926                 return test_path(targetpath, user_path, folder_name, subfolder_name);
927         } else {
928                 /* try $HOME/folder_name */
929                 return test_path(targetpath, user_path, NULL, folder_name);
930         }
931 }
932
933 static int get_path_system(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
934 {
935         char system_path[FILE_MAX];
936         const char *system_base_path;
937
938         system_path[0] = '\0';
939
940         if (test_env_path(system_path, envvar)) {
941                 if (subfolder_name) {
942                         return test_path(targetpath, system_path, NULL, subfolder_name);
943                 } else {
944                         BLI_strncpy(targetpath, system_path, FILE_MAX);
945                         return 1;
946                 }
947         }
948
949         system_base_path = (const char *)GHOST_getSystemDir();
950         if (system_base_path) {
951                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
952         }
953         
954         if(!system_path[0])
955                 return 0;
956         
957 #ifdef PATH_DEBUG2
958         printf("get_path_system: %s\n", system_path);
959 #endif
960         
961         if (subfolder_name) {
962                 /* try $BLENDERPATH/folder_name/subfolder_name */
963                 return test_path(targetpath, system_path, folder_name, subfolder_name);
964         } else {
965                 /* try $BLENDERPATH/folder_name */
966                 return test_path(targetpath, system_path, NULL, folder_name);
967         }
968 }
969
970 /* get a folder out of the 'folder_id' presets for paths */
971 /* returns the path if found, NULL string if not */
972 char *BLI_get_folder(int folder_id, char *subfolder)
973 {
974         static char path[FILE_MAX] = "";
975         
976         switch (folder_id) {
977                 case BLENDER_DATAFILES:         /* general case */
978                         if (get_path_local(path, "datafiles", subfolder)) break;
979                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
980                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
981                         return NULL;
982                         
983                 case BLENDER_USER_DATAFILES:
984                         if (get_path_local(path, "datafiles", subfolder)) break;
985                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
986                         return NULL;
987                         
988                 case BLENDER_SYSTEM_DATAFILES:
989                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES"))  break;
990                         return NULL;
991                         
992                 case BLENDER_CONFIG:            /* general case */
993                         if (get_path_local(path, "config", subfolder)) break;
994                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
995                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
996                         return NULL;
997                         
998                 case BLENDER_USER_CONFIG:
999                         if (get_path_local(path, "config", subfolder)) break;
1000                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1001                         return NULL;
1002                         
1003                 case BLENDER_SYSTEM_CONFIG:
1004                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1005                         return NULL;
1006                         
1007                 case BLENDER_SCRIPTS:           /* general case */
1008                         if (get_path_local(path, "scripts", subfolder)) break;
1009                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;           
1010                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1011                         return NULL;
1012                         
1013                 case BLENDER_USER_SCRIPTS:
1014                         if (get_path_local(path, "scripts", subfolder)) break;
1015                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1016                         return NULL;
1017                         
1018                 case BLENDER_SYSTEM_SCRIPTS:
1019                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1020                         return NULL;
1021                         
1022                 case BLENDER_PYTHON:            /* general case */
1023                         if (get_path_local(path, "python", subfolder)) break;
1024                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1025                         return NULL;
1026                         
1027                 case BLENDER_SYSTEM_PYTHON:
1028                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1029                         return NULL;
1030         }
1031         
1032         return path;
1033 }
1034
1035 static char *BLI_get_user_folder_notest(int folder_id, char *subfolder)
1036 {
1037         static char path[FILE_MAX] = "";
1038         char search_path[FILE_MAX];
1039
1040         switch (folder_id) {
1041                 case BLENDER_USER_DATAFILES:
1042                         BLI_join_dirfile(search_path, "datafiles", subfolder);
1043                         get_path_user(path, search_path, subfolder, "BLENDER_USER_DATAFILES");
1044                         break;
1045                 case BLENDER_USER_CONFIG:
1046                         BLI_join_dirfile(search_path, "config", subfolder);
1047                         get_path_user(path, search_path, subfolder, "BLENDER_USER_CONFIG");
1048                         break;
1049         }
1050         if ('\0' == path[0]) {
1051                 return NULL;
1052         }
1053         return path;
1054 }
1055
1056 char *BLI_get_folder_create(int folder_id, char *subfolder)
1057 {
1058         char *path;
1059
1060         /* only for user folders */
1061         if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG))
1062                 return NULL;
1063         
1064         path = BLI_get_folder(folder_id, subfolder);
1065         
1066         if (!path) {
1067                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1068                 if (path) BLI_recurdir_fileops(path);
1069         }
1070         
1071         return path;
1072 }
1073
1074
1075 /* End new stuff */
1076 /* ************************************************************* */
1077 /* ************************************************************* */
1078
1079
1080
1081 #ifdef PATH_DEBUG
1082 #undef PATH_DEBUG
1083 #endif
1084
1085 void BLI_setenv(const char *env, const char*val)
1086 {
1087         /* SGI or free windows */
1088 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)))
1089         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1090
1091         sprintf(envstr, "%s=%s", env, val);
1092         putenv(envstr);
1093         MEM_freeN(envstr);
1094
1095         /* non-free windows */
1096 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1097         _putenv_s(env, val);
1098 #else
1099         /* linux/osx/bsd */
1100         setenv(env, val, 1);
1101 #endif
1102 }
1103
1104
1105 /**
1106  Only set an env var if already not there.
1107  Like Unix setenv(env, val, 0);
1108  */
1109 void BLI_setenv_if_new(const char *env, const char* val)
1110 {
1111         if(getenv(env) == NULL)
1112                 BLI_setenv(env, val);
1113 }
1114
1115
1116 void BLI_clean(char *path)
1117 {
1118         if(path==0) return;
1119 #ifdef WIN32
1120         if(path && strlen(path)>2) {
1121                 BLI_char_switch(path+2, '/', '\\');
1122         }
1123 #else
1124         BLI_char_switch(path, '\\', '/');
1125 #endif
1126 }
1127
1128 void BLI_char_switch(char *string, char from, char to) 
1129 {
1130         if(string==0) return;
1131         while (*string != 0) {
1132                 if (*string == from) *string = to;
1133                 string++;
1134         }
1135 }
1136
1137 void BLI_make_exist(char *dir) {
1138         int a;
1139
1140         #ifdef WIN32
1141                 BLI_char_switch(dir, '/', '\\');
1142         #else
1143                 BLI_char_switch(dir, '\\', '/');
1144         #endif  
1145         
1146         a = strlen(dir);
1147         
1148 #ifdef WIN32    
1149         while(BLI_is_dir(dir) == 0){
1150                 a --;
1151                 while(dir[a] != '\\'){
1152                         a--;
1153                         if (a <= 0) break;
1154                 }
1155                 if (a >= 0) dir[a+1] = 0;
1156                 else {
1157                         /* defaulting to drive (usually 'C:') of Windows installation */
1158                         get_default_root(dir);
1159                         break;
1160                 }
1161         }
1162 #else
1163         while(BLI_is_dir(dir) == 0){
1164                 a --;
1165                 while(dir[a] != '/'){
1166                         a--;
1167                         if (a <= 0) break;
1168                 }
1169                 if (a >= 0) dir[a+1] = 0;
1170                 else {
1171                         strcpy(dir,"/");
1172                         break;
1173                 }
1174         }
1175 #endif
1176 }
1177
1178 void BLI_make_existing_file(char *name)
1179 {
1180         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1181
1182         strcpy(di, name);
1183         BLI_splitdirstring(di, fi);
1184         
1185         /* test exist */
1186         if (BLI_exists(di) == 0) {
1187                 BLI_recurdir_fileops(di);
1188         }
1189 }
1190
1191
1192 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1193 {
1194         int sl;
1195
1196         if (!string || !dir || !file) return; /* We don't want any NULLs */
1197         
1198         string[0]= 0; /* ton */
1199
1200         /* we first push all slashes into unix mode, just to make sure we don't get
1201            any mess with slashes later on. -jesterKing */
1202         /* constant strings can be passed for those parameters - don't change them - elubie */
1203         /*
1204         BLI_char_switch(relabase, '\\', '/');
1205         BLI_char_switch(dir, '\\', '/');
1206         BLI_char_switch(file, '\\', '/');
1207         */
1208
1209         /* Resolve relative references */       
1210         if (relabase && dir[0] == '/' && dir[1] == '/') {
1211                 char *lslash;
1212                 
1213                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1214                 strcpy(string, relabase);
1215                 
1216                 lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
1217                 
1218                 if(lslash) *(lslash+1)= 0;
1219
1220                 dir+=2; /* Skip over the relative reference */
1221         }
1222 #ifdef WIN32
1223         else {
1224                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1225                         BLI_strncpy(string, dir, 3);
1226                         dir += 2;
1227                 }
1228                 else { /* no drive specified */
1229                         /* first option: get the drive from the relabase if it has one */
1230                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1231                                 BLI_strncpy(string, relabase, 3);       
1232                                 string[2] = '\\';
1233                                 string[3] = '\0';
1234                         }
1235                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1236                                 get_default_root(string);
1237                         }
1238                         
1239                         /* ignore leading slashes */
1240                         while (*dir == '/' || *dir == '\\') dir++;
1241                 }
1242         }
1243 #endif
1244
1245         strcat(string, dir);
1246
1247         /* Make sure string ends in one (and only one) slash */ 
1248         /* first trim all slashes from the end of the string */
1249         sl = strlen(string);
1250         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1251                 string[sl-1] = '\0';
1252                 sl--;
1253         }
1254         /* since we've now removed all slashes, put back one slash at the end. */
1255         strcat(string, "/");
1256         
1257         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1258                 file++;
1259                 
1260         strcat (string, file);
1261         
1262         /* Push all slashes to the system preferred direction */
1263         BLI_clean(string);
1264 }
1265
1266 int BLI_testextensie(const char *str, const char *ext)
1267 {
1268         short a, b;
1269         int retval;
1270
1271         a= strlen(str);
1272         b= strlen(ext);
1273
1274         if(a==0 || b==0 || b>=a) {
1275                 retval = 0;
1276         } else if (BLI_strcasecmp(ext, str + a - b)) {
1277                 retval = 0;     
1278         } else {
1279                 retval = 1;
1280         }
1281
1282         return (retval);
1283 }
1284
1285 int BLI_replace_extension(char *path, int maxlen, const char *ext)
1286 {
1287         int a;
1288
1289         for(a=strlen(path)-1; a>=0; a--)
1290                 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1291                         break;
1292         
1293         if(path[a] != '.')
1294                 a= strlen(path);
1295
1296         if(a + strlen(ext) >= maxlen)
1297                 return 0;
1298
1299         strcpy(path+a, ext);
1300         return 1;
1301 }
1302
1303 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1304  * - wont change 'string'
1305  * - wont create any directories
1306  * - dosnt use CWD, or deal with relative paths.
1307  * - Only fill's in *dir and *file when they are non NULL
1308  * */
1309 void BLI_split_dirfile(const char *string, char *dir, char *file)
1310 {
1311         char *lslash_str = BLI_last_slash(string);
1312         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1313
1314         if (dir) {
1315                 if (lslash) {
1316                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1317                 } else {
1318                         dir[0] = '\0';
1319                 }
1320         }
1321         
1322         if (file) {
1323                 strcpy( file, string+lslash);
1324         }
1325 }
1326
1327 /* simple appending of filename to dir, does not check for valid path! */
1328 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1329 {
1330         int sl_dir;
1331         
1332         if(string != dir) /* compare pointers */
1333                 BLI_strncpy(string, dir, FILE_MAX);
1334
1335         if (!file)
1336                 return;
1337         
1338         sl_dir= BLI_add_slash(string);
1339         
1340         if (sl_dir <FILE_MAX) {
1341                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1342         }
1343 }
1344
1345 /* like pythons os.path.basename( ) */
1346 char *BLI_path_basename(char *path)
1347 {
1348         char *filename= BLI_last_slash(path);
1349         return filename ? filename + 1 : path;
1350 }
1351
1352 /*
1353   Produce image export path.
1354
1355   Fails returning 0 if image filename is empty or if destination path
1356   matches image path (i.e. both are the same file).
1357
1358   Trailing slash in dest_dir is optional.
1359
1360   Logic:
1361
1362   - if an image is "below" current .blend file directory, rebuild the
1363         same dir structure in dest_dir
1364
1365   For example //textures/foo/bar.png becomes
1366   [dest_dir]/textures/foo/bar.png.
1367
1368   - if an image is not "below" current .blend file directory,
1369   disregard it's path and copy it in the same directory where 3D file
1370   goes.
1371
1372   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1373
1374   This logic will help ensure that all image paths are relative and
1375   that a user gets his images in one place. It'll also provide
1376   consistent behaviour across exporters.
1377  */
1378 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)
1379 {
1380         char path[FILE_MAX];
1381         char dir[FILE_MAX];
1382         char base[FILE_MAX];
1383         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1384         char dest_path[FILE_MAX];
1385         char rel_dir[FILE_MAX];
1386         int len;
1387
1388         if (abs)
1389                 abs[0]= 0;
1390
1391         if (rel)
1392                 rel[0]= 0;
1393
1394         BLI_split_dirfile(base_dir, blend_dir, NULL);
1395
1396         if (src_dir[0]=='\0')
1397                 return 0;
1398
1399         BLI_strncpy(path, src_dir, sizeof(path));
1400
1401         /* expand "//" in filename and get absolute path */
1402         BLI_path_abs(path, base_dir);
1403
1404         /* get the directory part */
1405         BLI_split_dirfile(path, dir, base);
1406
1407         len= strlen(blend_dir);
1408
1409         rel_dir[0] = 0;
1410
1411         /* if image is "below" current .blend file directory */
1412         if (!strncmp(path, blend_dir, len)) {
1413
1414                 /* if image is _in_ current .blend file directory */
1415                 if (!strcmp(dir, blend_dir)) {
1416                         BLI_join_dirfile(dest_path, dest_dir, base);
1417                 }
1418                 /* "below" */
1419                 else {
1420                         /* rel = image_path_dir - blend_dir */
1421                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1422
1423                         BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1424                         BLI_join_dirfile(dest_path, dest_path, base);
1425                 }
1426
1427         }
1428         /* image is out of current directory */
1429         else {
1430                 BLI_join_dirfile(dest_path, dest_dir, base);
1431         }
1432
1433         if (abs)
1434                 BLI_strncpy(abs, dest_path, abs_size);
1435
1436         if (rel) {
1437                 strncat(rel, rel_dir, rel_size);
1438                 strncat(rel, base, rel_size);
1439         }
1440
1441         /* return 2 if src=dest */
1442         if (!strcmp(path, dest_path)) {
1443                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1444                 return 2;
1445         }
1446
1447         return 1;
1448 }
1449
1450
1451 static int add_win32_extension(char *name)
1452 {
1453         int retval = 0;
1454         int type;
1455
1456         type = BLI_exist(name);
1457         if ((type == 0) || S_ISDIR(type)) {
1458 #ifdef _WIN32
1459                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1460                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1461                 char *extensions = getenv("PATHEXT");
1462                 if (extensions) {
1463                         char *temp;
1464                         do {
1465                                 strcpy(filename, name);
1466                                 temp = strstr(extensions, ";");
1467                                 if (temp) {
1468                                         strncpy(ext, extensions, temp - extensions);
1469                                         ext[temp - extensions] = 0;
1470                                         extensions = temp + 1;
1471                                         strcat(filename, ext);
1472                                 } else {
1473                                         strcat(filename, extensions);
1474                                 }
1475
1476                                 type = BLI_exist(filename);
1477                                 if (type && (! S_ISDIR(type))) {
1478                                         retval = 1;
1479                                         strcpy(name, filename);
1480                                         break;
1481                                 }
1482                         } while (temp);
1483                 }
1484 #endif
1485         } else {
1486                 retval = 1;
1487         }
1488
1489         return (retval);
1490 }
1491
1492 void BLI_where_am_i(char *fullname, const char *name)
1493 {
1494         char filename[FILE_MAXDIR+FILE_MAXFILE];
1495         char *path = NULL, *temp;
1496         
1497 #ifdef _WIN32
1498         char *separator = ";";
1499         char slash = '\\';
1500 #else
1501         char *separator = ":";
1502         char slash = '/';
1503 #endif
1504
1505         
1506 #ifdef __linux__
1507         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1508         path = br_find_exe( NULL );
1509         if (path) {
1510                 BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE);
1511                 free(path);
1512                 return;
1513         }
1514 #endif
1515
1516 #ifdef _WIN32
1517         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1518                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1519                 return;
1520         }
1521 #endif
1522
1523         /* unix and non linux */
1524         if (name && fullname && strlen(name)) {
1525                 strcpy(fullname, name);
1526                 if (name[0] == '.') {
1527                         // relative path, prepend cwd
1528                         BLI_getwdN(fullname);
1529                         
1530                         // not needed but avoids annoying /./ in name
1531                         if(name && name[0]=='.' && name[1]==slash)
1532                                 BLI_join_dirfile(fullname, fullname, name+2);
1533                         else
1534                                 BLI_join_dirfile(fullname, fullname, name);
1535                         
1536                         add_win32_extension(fullname);
1537                 } else if (BLI_last_slash(name)) {
1538                         // full path
1539                         strcpy(fullname, name);
1540                         add_win32_extension(fullname);
1541                 } else {
1542                         // search for binary in $PATH
1543                         path = getenv("PATH");
1544                         if (path) {
1545                                 do {
1546                                         temp = strstr(path, separator);
1547                                         if (temp) {
1548                                                 strncpy(filename, path, temp - path);
1549                                                 filename[temp - path] = 0;
1550                                                 path = temp + 1;
1551                                         } else {
1552                                                 strncpy(filename, path, sizeof(filename));
1553                                         }
1554                                         BLI_join_dirfile(fullname, fullname, name);
1555                                         if (add_win32_extension(filename)) {
1556                                                 strcpy(fullname, filename);
1557                                                 break;
1558                                         }
1559                                 } while (temp);
1560                         }
1561                 }
1562 #ifndef NDEBUG
1563                 if (strcmp(name, fullname)) {
1564                         printf("guessing '%s' == '%s'\n", name, fullname);
1565                 }
1566 #endif
1567
1568 #ifdef _WIN32
1569                 // in windows change long filename to short filename because
1570                 // win2k doesn't know how to parse a commandline with lots of
1571                 // spaces and double-quotes. There's another solution to this
1572                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1573                 // that's even uglier
1574                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1575 #ifndef NDEBUG
1576                 printf("Shortname = '%s'\n", fullname);
1577 #endif
1578 #endif
1579         }
1580 }
1581
1582 void BLI_where_is_temp(char *fullname, int usertemp)
1583 {
1584         fullname[0] = '\0';
1585         
1586         if (usertemp && BLI_is_dir(U.tempdir)) {
1587                 strcpy(fullname, U.tempdir);
1588         }
1589         
1590         
1591 #ifdef WIN32
1592         if (fullname[0] == '\0') {
1593                 char *tmp = getenv("TEMP"); /* Windows */
1594                 if (tmp && BLI_is_dir(tmp)) {
1595                         strcpy(fullname, tmp);
1596                 }
1597         }
1598 #else
1599         /* Other OS's - Try TMP and TMPDIR */
1600         if (fullname[0] == '\0') {
1601                 char *tmp = getenv("TMP");
1602                 if (tmp && BLI_is_dir(tmp)) {
1603                         strcpy(fullname, tmp);
1604                 }
1605         }
1606         
1607         if (fullname[0] == '\0') {
1608                 char *tmp = getenv("TMPDIR");
1609                 if (tmp && BLI_is_dir(tmp)) {
1610                         strcpy(fullname, tmp);
1611                 }
1612         }
1613 #endif  
1614         
1615         if (fullname[0] == '\0') {
1616                 strcpy(fullname, "/tmp/");
1617         } else {
1618                 /* add a trailing slash if needed */
1619                 BLI_add_slash(fullname);
1620         }
1621 }
1622
1623 char *get_install_dir(void) {
1624         extern char bprogname[];
1625         char *tmpname = BLI_strdup(bprogname);
1626         char *cut;
1627
1628 #ifdef __APPLE__
1629         cut = strstr(tmpname, ".app");
1630         if (cut) cut[0] = 0;
1631 #endif
1632
1633         cut = BLI_last_slash(tmpname);
1634
1635         if (cut) {
1636                 cut[0] = 0;
1637                 return tmpname;
1638         } else {
1639                 MEM_freeN(tmpname);
1640                 return NULL;
1641         }
1642 }
1643
1644 #ifdef WITH_ICONV
1645
1646 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1647 {
1648         size_t inbytesleft=strlen(original);
1649         size_t outbytesleft=512;
1650         size_t rv=0;
1651         iconv_t cd;
1652         
1653         if (NULL == code) {
1654                 code = locale_charset();
1655         }
1656         cd=iconv_open("UTF-8", code);
1657
1658         if (cd == (iconv_t)(-1)) {
1659                 printf("iconv_open Error");
1660                 *utf_8='\0';
1661                 return ;
1662         }
1663         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1664         if (rv == (size_t) -1) {
1665                 printf("iconv Error\n");
1666                 return ;
1667         }
1668         *utf_8 = '\0';
1669         iconv_close(cd);
1670 }
1671 #endif // WITH_ICONV
1672
1673