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