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